Compare commits

...
235 Commits
Author SHA1 Message Date
Mr Chen 411798f4bf Merge pull request #221 from midoks/dev
0.10.0
2022-10-26 23:25:55 +08:00
midoks 2179db5f8b 0.10.0 2022-10-26 23:24:33 +08:00
midoks dcced8c0fb Update crontab_api.py 2022-10-26 22:08:29 +08:00
midoks 3e0e42d8a1 优化 2022-10-26 19:41:51 +08:00
midoks e5355d3e2f Update ftp_client.py 2022-10-26 18:56:57 +08:00
midoks 0a22e25611 Update ftp_client.py 2022-10-26 18:49:05 +08:00
midoks 5f7a3e5bf6 Update index.py 2022-10-26 18:43:48 +08:00
midoks 3518548c61 backup ftp 80% 2022-10-26 17:47:40 +08:00
midoks 08c4b0845d Update crontab_api.py 2022-10-26 11:34:52 +08:00
midoks 8f5fae8e79 Update index.py 2022-10-26 02:50:11 +08:00
midoks a151db1c30 Update install.sh 2022-10-26 02:48:08 +08:00
midoks 628c69ed22 Update index.html 2022-10-26 02:48:05 +08:00
midoks 13bcbc0f3e Update soft.js 2022-10-26 02:47:57 +08:00
midoks c94838462c backup_ftp 50% 2022-10-26 02:42:10 +08:00
midoks a147ef6962 Update centos.sh 2022-10-25 22:06:32 +08:00
midoks 4ccda15933 Update ftp.js 2022-10-25 14:11:49 +08:00
midoks 01074c743d Update pure-ftpd.conf 2022-10-25 14:10:46 +08:00
midoks 0871fa1763 up 2022-10-25 13:51:24 +08:00
midoks aade0ccd98 Update install.sh 2022-10-25 12:28:57 +08:00
midoks 4aed2f91de Update ftp.js 2022-10-25 12:28:49 +08:00
midoks d49dd9f2ac Update install.sh 2022-10-25 03:37:48 +08:00
midoks cff29194f4 Revert "安装优化"
This reverts commit ecbfb2500f.
2022-10-25 03:34:00 +08:00
midoks ecbfb2500f 安装优化 2022-10-25 03:20:35 +08:00
midoks 9c43170d4b Update install.sh 2022-10-25 03:11:06 +08:00
midoks 1239a2807f up 2022-10-25 02:53:19 +08:00
midoks 1c0a130b49 up 2022-10-25 01:43:29 +08:00
midoks ffb1eb34e0 waf 0.2.3 2022-10-25 00:41:27 +08:00
midoks 82874d1f7a Update url_white.json 2022-10-24 23:42:26 +08:00
midoks 4e05f29fcd OP防火墙-0.2.3 2022-10-24 23:12:45 +08:00
midoks d5f3b0d442 初始安装 ipv6 优化 2022-10-24 21:55:44 +08:00
midoks 81eec04037 Update mw.tpl 2022-10-24 21:44:34 +08:00
midoks 5a5dc43e17 Update mw.tpl 2022-10-24 21:38:10 +08:00
midoks b4eb2b3192 Update mw.tpl 2022-10-24 21:20:04 +08:00
midoks 2d1c070e1b Update mw.tpl 2022-10-24 21:16:17 +08:00
midoks 81364fdfa3 Update common.lua 2022-10-24 21:12:41 +08:00
midoks 9d0d88d465 Update init.lua 2022-10-24 20:56:18 +08:00
midoks 7e2eef8bbf Update init.lua 2022-10-24 20:54:41 +08:00
midoks 8d1315e5be Update init.lua 2022-10-24 20:39:07 +08:00
midoks fe6a51540e Update init.lua 2022-10-24 20:38:24 +08:00
midoks 6e35683505 Update init.lua 2022-10-24 20:35:39 +08:00
midoks 713c0d1a3c up 2022-10-24 20:18:34 +08:00
midoks 8323e0ec73 up 2022-10-24 20:06:38 +08:00
midoks 6eae94658f up 2022-10-24 19:55:09 +08:00
midoks 07d173d2cf up 2022-10-24 19:11:48 +08:00
midoks 23f2b9efac Update index.py 2022-10-24 15:14:14 +08:00
midoks 9b2ab9276c Update common.lua 2022-10-24 14:53:54 +08:00
midoks 7903e1a286 Update common.lua 2022-10-24 14:53:39 +08:00
midoks 662e05511f Update common.lua 2022-10-24 14:51:58 +08:00
midoks 1f8785acbc Update init.lua 2022-10-24 14:49:20 +08:00
midoks 3eb87cf953 Update init.lua 2022-10-24 11:57:46 +08:00
midoks 124b24885e Update op_waf.js 2022-10-24 11:23:35 +08:00
midoks 2196983455 Update ip_white.json 2022-10-24 11:22:39 +08:00
midoks 80a67c4f58 Update webstats_log.lua 2022-10-24 11:10:23 +08:00
midoks ff06f7ef91 Update webstats_common.lua 2022-10-24 11:06:35 +08:00
midoks b16506c8bc #211 优化
phpmyadmin安全设置处修改端口保存后当前用修改后的端口能打开,一旦停止phpmyadmin后,再重启phpmyadmin端口又变为888,需要手工再次改变
2022-10-23 14:07:18 +08:00
midoks 2d3801dcc0 up 2022-10-23 13:49:08 +08:00
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
106 changed files with 5439 additions and 1712 deletions
+5
View File
@@ -0,0 +1,5 @@
# These are supported funding model platforms
github: midoks
custom: https://afdian.net/a/mdserver-web
+11 -9
View File
@@ -65,6 +65,8 @@ phpMyAdmin[5.2.0]支持MySQL[8.0]
PHP[53-72]支持phpMyAdmin[4.4.15] PHP[53-72]支持phpMyAdmin[4.4.15]
PHP[72-81]支持phpMyAdmin[5.2.0] PHP[72-81]支持phpMyAdmin[5.2.0]
``` ```
# 特别赞助 # 特别赞助
@@ -78,7 +80,7 @@ PHP[72-81]支持phpMyAdmin[5.2.0]
| 服务商 | LOGO | 推广地址 | 优惠码 | | 服务商 | 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 | | 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 # Docker
@@ -90,15 +92,15 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
``` ```
### 版本更新 0.9.13 ### 版本更新 0.10.0
* OP防火墙优化。
* OP防火墙-添加URL白名单功能。
* 网站统计优化。
* 添加`FTP存储空间`插件。
* 初始安装IPv6安装。
* phpMyAdmin优化。
* 优化弹框。
* 修复计划任务[日志切割]。
* 优化mysql的与phpmyadmin的连接。
* PHP添加`会话管理`功能。
* redis优化。
* 更新mysql[5.7]的安装。
* OP防火墙部分功能优化。
### JSDelivr安装地址 ### JSDelivr安装地址
+1 -1
View File
@@ -85,7 +85,7 @@ def initInitD():
mw.execShell('mkdir -p /etc/init.d') mw.execShell('mkdir -p /etc/init.d')
# initd # initd
if os.path.exists("/etc/init.d"): if os.path.exists('/etc/init.d'):
initd_bin = '/etc/init.d/mw' initd_bin = '/etc/init.d/mw'
if not os.path.exists(initd_bin): if not os.path.exists(initd_bin):
import shutil import shutil
+1 -1
View File
@@ -15,7 +15,7 @@ from flask import request
class config_api: class config_api:
__version = '0.9.13' __version = '0.10.0'
def __init__(self): def __init__(self):
pass pass
+22 -5
View File
@@ -68,8 +68,8 @@ class crontab_api:
_list[i]['where_hour']), str(_list[i]['where_minute']))) _list[i]['where_hour']), str(_list[i]['where_minute'])))
data.append(tmp) data.append(tmp)
_ret = {} rdata = {}
_ret['data'] = data rdata['data'] = data
count = mw.M('crontab').where('', ()).count() count = mw.M('crontab').where('', ()).count()
_page = {} _page = {}
@@ -78,9 +78,17 @@ class crontab_api:
_page['row'] = psize _page['row'] = psize
_page['tojs'] = "getCronData" _page['tojs'] = "getCronData"
_ret['list'] = mw.getPage(_page) rdata['list'] = mw.getPage(_page)
_ret['p'] = p rdata['p'] = p
return mw.getJson(_ret)
# backup hock
bh_file = mw.getPanelDataDir() + "/hook_backup.json"
if os.path.exists(bh_file):
hb_data = mw.readFile(bh_file)
hb_data = json.loads(hb_data)
rdata['backup_hook'] = hb_data
return mw.getJson(rdata)
# 设置计划任务状态 # 设置计划任务状态
def setCronStatusApi(self): def setCronStatusApi(self):
@@ -409,6 +417,15 @@ class crontab_api:
shell = param.sFile shell = param.sFile
else: else:
head = "#!/bin/bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n" head = "#!/bin/bash\nPATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin\nexport PATH\n"
source_bin_activate = '''
MW_PATH=%s/bin/activate
if [ -f $MW_PATH ];then
source $MW_PATH
fi
''' % (mw.getRunDir(),)
head = head + source_bin_activate + "\n"
log = '.log' log = '.log'
script_dir = mw.getServerDir() + "/mdserver-web/scripts" script_dir = mw.getServerDir() + "/mdserver-web/scripts"
+12 -5
View File
@@ -161,19 +161,24 @@ def isInstalledWeb():
def restartWeb(): def restartWeb():
return opWeb("reload")
def opWeb(method):
if not isInstalledWeb(): if not isInstalledWeb():
return False return False
# systemd # systemd
systemd = '/lib/systemd/system/openresty.service' systemd = '/lib/systemd/system/openresty.service'
if os.path.exists(systemd): if os.path.exists(systemd):
execShell('systemctl reload openresty') execShell('systemctl ' + method + ' openresty')
return True return True
# initd # initd
initd = getServerDir() + '/openresty/init.d/openresty' initd = getServerDir() + '/openresty/init.d/openresty'
if os.path.exists(initd): if os.path.exists(initd):
execShell(initd + ' ' + 'reload') execShell(initd + ' ' + method)
return True return True
return False return False
@@ -595,12 +600,14 @@ def getLastLine(path, num, p=1):
count = start_line + num count = start_line + num
fp = open(path, 'rb') fp = open(path, 'rb')
buf = "" buf = ""
fp.seek(-1, 2)
fp.seek(0, 2)
if fp.read(1) == "\n": if fp.read(1) == "\n":
fp.seek(-1, 2) fp.seek(0, 2)
data = [] data = []
b = True b = True
n = 0 n = 0
for i in range(count): for i in range(count):
while True: while True:
newline_pos = str.rfind(str(buf), "\n") newline_pos = str.rfind(str(buf), "\n")
@@ -717,7 +724,7 @@ def checkIp(ip):
def checkPort(port): def checkPort(port):
# 检查端口是否合法 # 检查端口是否合法
ports = ['21', '25', '7200', '888'] ports = ['21', '25', '443', '888']
if port in ports: if port in ports:
return False return False
intport = int(port) intport = int(port)
+1 -1
View File
@@ -9,7 +9,7 @@ if [ -f bin/activate ];then
source bin/activate source bin/activate
fi fi
# export LC_ALL="en_US.UTF-8" export LC_ALL="en_US.UTF-8"
mw_start_task() mw_start_task()
+418
View File
@@ -0,0 +1,418 @@
# coding:utf-8
'''
doc: https://docs.python.org/zh-cn/3/library/ftplib.html
'''
import sys
import io
import os
import time
import re
import json
import paramiko
import ftplib
sys.path.append(os.getcwd() + "/class/core")
import mw
DEBUG = True
BLOCK_SIZE = 1024 * 1024 * 2
# BLOCK_SIZE = 50
PROGRESS_FILE_NAME = "PROGRESS_FILE_NAME"
"""
=============自定义异常===================
"""
class OsError(Exception):
"""OS端异常"""
class ObjectNotFound(OsError):
"""对象不存在时抛出的异常"""
def __init__(self, *args, **kwargs):
message = "文件对象不存在。"
super(ObjectNotFound, self).__init__(message, *args, **kwargs)
class APIError(Exception):
"""API参数错误异常"""
def __init__(self, *args, **kwargs):
_api_error_msg = 'API资料校验失败,请核实!'
super(APIError, self).__init__(_api_error_msg, *args, **kwargs)
class FtpPSClient:
_title = "FTP"
_name = "ftp"
__host = None
__port = None
__user = None
__password = None
default_port = 21
default_backup_path = "/backup/"
config_file = "cfg.json"
def __init__(self, load_config=True, timeout=10):
self.timeout = timeout
if load_config:
data = self.get_config()
self.injection_config(data)
def get_config(self):
default_config = {
"ftp_host": '',
"ftp_user": '',
"ftp_pass": '',
"backup_path": self.default_backup_path
}
cfg = mw.getServerDir() + "/backup_ftp/" + self.config_file
if os.path.exists(cfg):
data = mw.readFile(cfg)
return json.loads(data)
else:
return default_config
def injection_config(self, data):
host = data["ftp_host"].strip()
if host.find(':') == -1:
self.__port = self.default_port
self.__host = data['ftp_host'].strip()
self.__user = data['ftp_user'].strip()
self.__password = data['ftp_pass'].strip()
bp = data['backup_path'].strip()
if bp:
self.backup_path = self.getPath(bp)
else:
self.backup_path = self.getPath(self.default_backup_path)
def authorize(self):
try:
if self.timeout is not None:
ftp = ftplib.FTP(timeout=self.timeout)
else:
ftp = ftplib.FTP()
debuglevel = 0
# if DEBUG:
# debuglevel = 3
ftp.set_debuglevel(debuglevel)
# ftp.set_pasv(True)
ftp.connect(self.__host, int(self.__port))
ftp.login(self.__user, self.__password)
return ftp
except Exception as e:
raise OsError("无法连接FTP客户端,请检查配置参数是否正确!")
# 取目录路径
def getPath(self, path):
if path[-1:] != '/':
path += '/'
if path[:1] != '/':
path = '/' + path
return path.replace('//', '/')
def generateDownloadUrl(self, object_name):
return 'ftp://' + \
self.__user + ':' + \
self.__password + '@' + \
self.__host + ':' + \
"/" + object_name
def buildDirName(self, data_type, file_name):
import re
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
file_regx = prefix_dict.get(data_type) + "_(.+)_20\d+_\d+\."
sub_search = re.search(file_regx, file_name)
sub_path_name = ""
if sub_search:
sub_path_name = sub_search.groups()[0]
sub_path_name += '/'
# 构建OS存储路径
object_name = self.backup_path + \
data_type + '/' + \
sub_path_name + \
file_name
return object_name
def uploadFile(self, filename, data_type=None, *args, **kwargs):
client = self.authorize()
local_file_name = filename
filename = os.path.abspath(filename)
dirname = os.path.dirname(filename)
temp_name = os.path.split(filename)[1]
object_name = self.buildDirName(data_type, temp_name)
upload_tmp_dir = os.path.join(dirname, ".upload_tmp")
if not os.path.exists(upload_tmp_dir):
os.mkdir(upload_tmp_dir)
print("|-正在上传文件到 {}".format(object_name))
total_bytes = os.path.getsize(filename)
object_md5_name = mw.md5(object_name)
pg_file = os.path.join(upload_tmp_dir, object_md5_name + ".pl")
block_size = BLOCK_SIZE
if kwargs.get("block_size"):
try:
block_size = float(kwargs.get("block_size"))
except:
pass
remote_file_size = None
if not os.path.exists(pg_file):
# import uuid
# uid = str(uuid.uuid1())
progress_info = {
"filename": local_file_name,
"total_bytes": total_bytes,
"uploaded_bytes": 0,
}
mw.writeFile(pg_file, json.dumps(progress_info))
else:
progress_info = json.loads(public.readFile(pg_file))
if total_bytes == progress_info.get("total_bytes"):
# 取远程文件大小
_max_loop = 10
while _max_loop > 0:
try:
time.sleep(1)
remote_file_size = client.size(object_name)
if remote_file_size > total_bytes:
remote_file_size = None
break
except Exception as e:
if DEBUG:
print(type(e))
print(e)
_max_loop -= 1
else:
remote_file_size = None
uploaded_bytes = 0 if remote_file_size is None else remote_file_size
dir_name = os.path.split(object_name)[0]
if dir_name:
self.createDirP(dir_name)
upload_start = time.time()
try:
if total_bytes > 1024 * 1024 * 1024:
with open(local_file_name, 'rb') as file_handler:
if remote_file_size is not None:
file_handler.seek(remote_file_size)
client.voidcmd("TYPE I")
datasock = ''
esize = ''
datasock, esize = client.ntransfercmd(
"STOR " + object_name, remote_file_size)
while True:
buf = file_handler.read(block_size)
if not len(buf):
break
datasock.sendall(buf)
uploaded_bytes += len(buf)
if DEBUG:
print('\ruploading %.2f%%' %
(float(uploaded_bytes) / total_bytes * 100))
print("uploaded_bytes", uploaded_bytes)
if uploaded_bytes == total_bytes:
break
datasock.close()
if DEBUG:
print('close data handle')
try:
client.voidcmd('NOOP')
except Exception as e:
if DEBUG:
print("Send NOOP command error:")
print(e)
else:
if DEBUG:
print('keep alive cmd success')
client.voidresp()
if DEBUG:
print('No loop cmd')
else:
# 小于1G文件直接上传
file_handler = open(local_file_name, "rb")
client.storbinary('STOR %s' % object_name,
file_handler, blocksize=block_size)
file_handler.close()
except Exception as e:
print(str(e))
completed_file_size = None
_max_loop = 10
while _max_loop > 0:
try:
time.sleep(1)
completed_file_size = client.size(object_name)
break
except Exception as e:
_max_loop -= 1
if DEBUG:
print("size error:" + str(e))
# 上传完成
if completed_file_size == total_bytes:
if DEBUG:
upload_completed = time.time()
upload_diff = upload_completed - upload_start
print("文件上传成功, 耗时: {}s。".format(upload_diff))
if os.path.exists(pg_file):
os.remove(pg_file)
return True
else:
if os.path.exists(pg_file):
os.remove(pg_file)
print("文件上传后大小不一致!")
print("completed_file_size:" + str(completed_file_size))
print("total_bytes:", total_bytes)
print("object_md5_name:", object_md5_name)
print("pg_file:", pg_file)
print("filename:", filename)
print("dirname:", dirname)
print("object_name:", object_name)
return False
def createDirP(self, dir_name):
"""创建远程目录
:param dir_name: 目录名称
:return:
"""
try:
dirnames = dir_name.split('/')
ftp = self.authorize()
# ftp.cwd(get.path);
for dirname in dirnames:
if not dirname or not dirname.strip():
continue
try:
flist = ftp.nlst()
if not dirname in flist:
ftp.mkd(dirname)
except:
# print("mlsd mode.")
try:
flist = list(ftp.mlsd())[1:]
for f in flist:
if dirname == f[0]:
break
else:
ftp.mkd(dirname)
except:
return False
ftp.cwd(dirname)
return True
except:
return False
def createDir(self, path, name):
ftp = self.authorize()
path = self.getPath(path)
ftp.cwd(path)
try:
ftp.mkd(name)
ftp.close()
return True
except Exception as e:
print(str(e))
ftp.close()
return False
def deleteDir(self, path, dir_name):
try:
ftp = self.authorize()
ftp.rmd(dir_name)
return True
except ftplib.error_perm as e:
print(str(e) + ":" + dir_name)
except Exception as e:
print(e)
return False
def deleteFile(self, filename):
try:
ftp = self.authorize()
ftp.delete(filename)
return True
except Exception as e:
print(str(e))
return False
def getList(self, path="/"):
ftp = self.authorize()
path = self.getPath(path)
ftp.cwd(path)
mlsd = False
try:
files = list(ftp.mlsd())
mlsd = True
except:
try:
files = ftp.nlst(path)
mlsd = False
except:
raise RuntimeError("FTP服务器数据返回异常!")
ftp.close()
# print(files)
f_list = []
dirs = []
data = []
default_time = '1971/01/01 01:01:01'
for dt in files:
# print(dt)
if mlsd:
dt_name = dt[0]
dt_info = dt[1]
else:
if dt.find("/") >= 0:
dt = dt.split("/")[-1]
tmp = {}
tmp['name'] = dt_name
if dt_name == '.' or dt_name == '..':
continue
tmp['time'] = dt_info['modify']
try:
tmp['size'] = dt_info['size']
tmp['type'] = "File"
tmp['download'] = self.generateDownloadUrl(path + dt_name)
f_list.append(tmp)
except:
tmp['size'] = dt_info['sizd']
tmp['type'] = None
tmp['download'] = ''
dirs.append(tmp)
data = dirs + f_list
mlist = {}
mlist['path'] = path
mlist['list'] = data
return mlist
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

+101
View File
@@ -0,0 +1,101 @@
<style>
.upyunCon {
height: 428px;
}
.up-place {
height: 62px;
border-bottom: 1px solid #ddd;
}
.up-place .btn {
border-radius: 0;
}
.up-place .place-input {
background-color: #f3f3f3;
border: 1px solid #ccc;
height: 30px;
line-height: 28px;
overflow: hidden;
margin: 1px 0 0 -1px;
width: 340px;
}
.place-input ul {
display: inline-block;
position: relative;
width: auto;
}
.place-input ul li {
background: url("/static/img/ico/ico-ltr.png") no-repeat right center;
float: left;
padding-left: 10px;
padding-right: 18px;
}
.place-input ul li a {
height: 28px;
cursor: pointer;
display: inline-block;
}
.upyunlist {
height: 516px;
overflow: auto;
}
.up-bottom {
background-color: #fafafa;
border-top: 1px solid #eee;
bottom: 0;
position: absolute;
width: 100%;
}
.up-use {
line-height: 50px
}
.list-list .cursor span {
line-height: 30px;
}
.btn-title {
margin-top: 1px
}
.tip {
font-size: 10px;
font-style: oblique;
color: green;
}
</style>
<div class="upyunCon">
<div class="up-place pd15">
<button id="backBtn" class="btn btn-default btn-sm glyphicon glyphicon-arrow-left pull-left" title="后退"></button>
<input id="myPath" style="display:none;" type="text" value="">
<div class="place-input pull-left">
<div style="width:1400px;height:28px"><ul></ul></div>
</div>
<button class="refreshBtn btn btn-default btn-sm glyphicon glyphicon-refresh pull-left mr20" title="刷新" style="margin-left:-1px;"></button>
<button class="btn btn-default btn-sm pull-right btn-title" onclick="upyunApi()">帐户设置</button>
<button class="btn btn-default btn-sm pull-right mr20 btn-title" onclick="createDir()">新建文件夹</button>
</div>
<div class="upyunlist pd15">
<div class="divtable" style="margin-bottom:15px">
<table class="table table-hover">
<thead><tr><th>名称</th><th>大小</th><th>更新时间</th><th class="text-right">操作</th></tr></thead>
<tbody class="list-list"></tbody>
</table>
</div>
</div>
</div>
<script type="text/javascript">
$.getScript( "/plugins/file?name=backup_ftp&f=js/backup_ftp.js", function(){
osList('/');
});
</script>
+250
View File
@@ -0,0 +1,250 @@
# coding:utf-8
import sys
import io
import os
import time
import re
import json
sys.path.append(os.getcwd() + "/class/core")
import mw
_ver = sys.version_info
is_py2 = (_ver[0] == 2)
is_py3 = (_ver[0] == 3)
DEBUG = False
if is_py2:
reload(sys)
sys.setdefaultencoding('utf-8')
app_debug = False
if mw.isAppleSystem():
app_debug = True
def getPluginName():
return 'backup_ftp'
def getPluginDir():
return mw.getPluginDir() + '/' + getPluginName()
sys.path.append(getPluginDir() + "/class")
from ftp_client import FtpPSClient
def getServerDir():
return mw.getServerDir() + '/' + 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 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 status():
return 'start'
def getConf():
cfg = getServerDir() + "/cfg.json"
if not os.path.exists(cfg):
return mw.returnJson(False, "未配置", [])
data = mw.readFile(cfg)
data = json.loads(data)
return mw.returnJson(True, "OK", data)
def setConf():
args = getArgs()
data = checkArgs(args, ['use_sftp', 'ftp_user',
'ftp_pass', 'ftp_host', 'backup_path'])
if not data[0]:
return data[1]
cfg = getServerDir() + "/cfg.json"
values = ['ftp_user',
'ftp_pass',
'ftp_host']
for v in values:
if args[v] == '':
return mw.returnJson(False, '必填资料不能为空,请核实!', [])
if args['backup_path'] == '':
args['backup_path'] = "/backup"
try:
ftp = FtpPSClient(load_config=False)
ftp.injection_config(args)
data = ftp.getList("/")
if data:
mw.writeFile(cfg, mw.getJson(args))
return mw.returnJson(True, '设置成功', [])
except Exception as e:
return mw.returnJson(False, "FTP校验失败,请核实!\n" + str(e), [])
def getList():
cfg = getServerDir() + "/cfg.json"
if not os.path.exists(cfg):
return mw.returnJson(False, "未配置FTP,请点击`账户设置`", [])
args = getArgs()
data = checkArgs(args, ['path'])
if not data[0]:
return data[1]
try:
ftp = FtpPSClient()
flist = ftp.getList(args['path'])
return mw.returnJson(True, "ok", flist)
except Exception as e:
return mw.returnJson(False, str(e), [])
def createDir():
cfg = getServerDir() + "/cfg.json"
if not os.path.exists(cfg):
return mw.returnJson(False, "未配置FTP,请点击`账户设置`", [])
args = getArgs()
data = checkArgs(args, ['path', 'name'])
if not data[0]:
return data[1]
ftp = FtpPSClient()
isok = ftp.createDir(args['path'], args['name'])
if isok:
return mw.returnJson(True, "创建成功")
return mw.returnJson(False, "创建失败")
def deleteDir():
args = getArgs()
data = checkArgs(args, ['dir_name', 'path'])
if not data[0]:
return data[1]
ftp = FtpPSClient()
isok = ftp.deleteDir(args['path'], args['dir_name'])
if isok:
return mw.returnJson(True, "删除成功")
return mw.returnJson(False, "删除失败")
def deleteFile():
args = getArgs()
data = checkArgs(args, ['path', 'filename'])
if not data[0]:
return data[1]
ftp = FtpPSClient()
isok = ftp.deleteFile(args['path'] + "/" + args['filename'])
if isok:
return mw.returnJson(True, "删除成功")
return mw.returnJson(False, "删除失败")
def backupAllFunc(stype):
os.chdir(mw.getRunDir())
name = sys.argv[2]
num = sys.argv[3]
args = stype + " " + name + " " + num
cmd = 'python3 ' + mw.getRunDir() + '/scripts/backup.py ' + args
os.system(cmd)
# 开始执行上传信息
prefix_dict = {
"site": "web",
"database": "db",
"path": "path",
}
find_path = mw.getBackupDir() + '/' + stype + '/' + \
prefix_dict[stype] + '_' + name
find_new_file = "ls " + find_path + \
"_* | grep tar.gz | cut -d \ -f 1 | awk 'END {print}'"
filename = mw.execShell(find_new_file)[0].strip()
# print("filename:", filename)
ftp = FtpPSClient()
ftp.uploadFile(filename, stype)
return True
def backupSite():
# 备份站点
pass
def in_array(name, arr=[]):
for x in arr:
if name == x:
return True
return False
def installPreInspection():
return 'ok'
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 == 'install_pre_inspection':
print(installPreInspection())
elif func == 'conf':
print(getConf())
elif func == 'set_config':
print(setConf())
elif func == "get_list":
print(getList())
elif func == "create_dir":
print(createDir())
elif func == "delete_dir":
print(deleteDir())
elif func == 'delete_file':
print(deleteFile())
elif in_array(func, ['site', 'database', 'path']):
print(backupAllFunc(func))
else:
print('error')
+17
View File
@@ -0,0 +1,17 @@
{
"title":"FTP存储空间",
"hook":["backup"],
"tip":"soft",
"name":"backup_ftp",
"type":"运行环境",
"ps":"将网站或数据库打包备份到FTP存储空间",
"versions":["1.0"],
"install_pre_inspection":false,
"shell":"install.sh",
"checks":"server/backup_ftp",
"path": "server/backup_ftp",
"author":"midoks",
"home":"",
"date":"2022-10-23",
"pid": "4"
}
+32
View File
@@ -0,0 +1,32 @@
#!/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
sys_os=`uname`
Install_App()
{
mkdir -p ${serverPath}/backup_ftp
echo "${1}" > ${serverPath}/backup_ftp/version.pl
echo '安装完成' > $install_tmp
}
Uninstall_App()
{
rm -rf ${serverPath}/backup_ftp
}
action=$1
if [ "${1}" == 'install' ];then
Install_App $2
else
Uninstall_App $2
fi
+258
View File
@@ -0,0 +1,258 @@
function bkfPost(method,args,callback){
var _args = null;
if (typeof(args) == 'string'){
_args = JSON.stringify(toArrayObject(args));
} else {
_args = JSON.stringify(args);
}
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
$.post('/plugins/run', {name:'backup_ftp', 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 getFtpLocalTime(data){
var str = data.slice(0,4)+"/"+data.slice(4,6)+"/"+data.slice(6,8)
+ " " + data.slice(8,10)+":"+data.slice(10,12)+":"+data.slice(12,14);
return str;
}
// 自定义部分
var i = null;
//设置API
function upyunApi(){
bkfPost('conf', {}, function(rdata){
var rdata = $.parseJSON(rdata.data);
var token = rdata.data;
var check_status = token.use_sftp;
var sftp_checked = check_status === "true" ? " checked=\"checked\"" : "";
if (typeof(token.ftp_host) == 'undefined'){
token.ftp_host = '';
}
if (typeof(token.ftp_user) == 'undefined'){
token.ftp_user = '';
}
if (typeof(token.ftp_pass) == 'undefined'){
token.ftp_pass = '';
}
if (typeof(token.backup_path) == 'undefined'){
token.backup_path = '';
}
var apicon = '<div class="bingfa mtb15" style="padding-bottom:0px;">\
<p>\
<span class="span_tit">使用SFTP:</span>\ <input style="width: 20px; vertical-align:middle;" type="checkbox" name="use_sftp"'+sftp_checked+'> 是否使用SFTP进行数据传输 \
</p>\
<p>\
<span class="span_tit">Host:</span>\
<input placeholder="请输入主机地址" style="width: 200px;" type="text" name="upyun_service" value="'+token.ftp_host+'"> *服务器地址,FTP默认端口21, SFTP默认端口22\
</p>\
<p>\
<span class="span_tit">用户名:</span>\
<input style="width: 200px;" type="text" name="ftp_username" value="'+token.ftp_user+'"> *指定用户名\
</p>\
<p>\
<span class="span_tit">密码:</span>\
<input style="width: 200px;" type="password" name="ftp_password" value="'+token.ftp_pass+'"> *登录密码\
</p>\
<p>\
<span class="span_tit">存储位置:</span>\
<input placeholder="请输入存储位置" style="width: 200px;" type="text" name="backup_path" value="'+token.backup_path+'"> *相对于根目录的路径,默认是/backup\
</p>\
</div>';
layer.open({
type: 1,
area: "600px",
title: "FTP/SFTP帐户设置",
closeBtn: 1,
shift: 5,
shadeClose: false,
btn: ['确定','取消'],
content:apicon,
yes:function(index,layero){
var data = {
use_sftp:$("input[name='use_sftp']").prop('checked'),
ftp_user:$("input[name='ftp_username']").val(),
ftp_pass:$("input[name='ftp_password']").val(),
ftp_host:$("input[name='upyun_service']").val(),
backup_path:$("input[name='backup_path']").val()
}
bkfPost('set_config', data, function(rdata){
var rdata = $.parseJSON(rdata.data);
if (rdata.status){
showMsg(rdata.msg,function(){
layer.close(index);
osList("/");
},{icon:1},2000);
} else{
layer.msg(rdata.msg,{icon:2});
}
})
},
});
});
}
function createDir(){
layer.open({
type: 1,
area: "400px",
title: "创建目录",
closeBtn: 1,
shift: 5,
shadeClose: false,
btn: ['确定','取消'],
content:'<div class="bingfa bt-form c6" style="padding-bottom: 10px;">\
<p>\
<span class="span_tit">目录名称:</span>\
<input style="width: 200px;" type="text" name="newPath" value="">\
</p>\
</div>',
success:function(){
$("input[name='newPath']").focus().keyup(function(e){
if(e.keyCode == 13) $(".layui-layer-btn0").click();
});
},
yes:function(index,layero){
var name = $("input[name='newPath']").val();
if(name == ''){
layer.msg('目录名称不能为空!',{icon:2});
return;
}
var path = $("#myPath").val();
var dirname = name;
// var loadT = layer.msg('正在创建目录['+dirname+']...',{icon:16,time:0,shade: [0.3, '#000']});
bkfPost('create_dir', {path:path,name:dirname}, function(data){
var rdata = $.parseJSON(data.data);
if(rdata.status) {
showMsg(rdata.msg, function(){
layer.close(index);
osList(path);
} ,{icon:1}, 2000);
} else{
layer.msg(rdata.msg,{icon:2});
}
});
}
});
}
//删除文件
function deleteFile(name, is_dir){
if (is_dir === false){
safeMessage('删除文件','删除后将无法恢复,真的要删除['+name+']吗?',function(){
var path = $("#myPath").val();
var filename = name;
bkfPost('delete_file', {filename:filename,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
osList(path);
},{icon:rdata.status?1:2},2000);
});
});
} else {
safeMessage('删除文件夹','删除后将无法恢复,真的要删除['+name+']吗?',function(){
var path = $("#myPath").val();
bkfPost('delete_dir', {dir_name:name,path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
showMsg(rdata.msg,function(){
osList(path);
},{icon:rdata.status?1:2},2000);
});
});
}
}
function osList(path){
bkfPost('get_list', {path:path}, function(rdata){
var rdata = $.parseJSON(rdata.data);
if(rdata.status === false){
showMsg(rdata.msg,function(){
upyunApi();
},{icon:2},2000);
return;
}
var mlist = rdata.data;
// console.log(mlist);
var listBody = ''
var listFiles = ''
for(var i=0;i<mlist.list.length;i++){
if(mlist.list[i].type == null){
listBody += '<tr><td class="cursor" onclick="osList(\''+(path+'/'+mlist.list[i].name).replace('//','/')+'\')"><span class="ico ico-folder"></span>\<span>'+mlist.list[i].name+'</span></td>\
<td>-</td>\
<td>-</td>\
<td class="text-right"><a class="btlink" onclick="deleteFile(\''+mlist.list[i].name+'\', true)">删除</a></td></tr>'
}else{
listFiles += '<tr><td class="cursor"><span class="ico ico-file"></span>\<span>'+mlist.list[i].name+'</span></td>\
<td>'+toSize(mlist.list[i].size)+'</td>\
<td>'+getFtpLocalTime(mlist.list[i].time)+'</td>\
<td class="text-right"><a target="_blank" href="'+mlist.list[i].download+'" class="btlink">下载</a> | <a class="btlink" onclick="deleteFile(\''+mlist.list[i].name+'\', false)">删除</a></td></tr>'
}
}
listBody += listFiles;
var pathLi='';
var tmp = path.split('/')
var pathname = '';
var n = 0;
for(var i=0;i<tmp.length;i++){
if(n > 0 && tmp[i] == '') continue;
var dirname = tmp[i];
if(dirname == '') {
dirname = '根目录';
n++;
}
pathname += '/' + tmp[i];
pathname = pathname.replace('//','/');
pathLi += '<li><a title="'+pathname+'" onclick="osList(\''+pathname+'\')">'+dirname+'</a></li>';
}
var um = 1;
if(tmp[tmp.length-1] == '') um = 2;
var backPath = tmp.slice(0,tmp.length-um).join('/') || '/';
$('#myPath').val(path);
$(".upyunCon .place-input ul").html(pathLi);
$(".upyunlist .list-list").html(listBody);
upPathLeft();
$('#backBtn').unbind().click(function() {
osList(backPath);
});
$('.upyunCon .refreshBtn').unbind().click(function(){
osList(path);
});
});
}
//计算当前目录偏移
function upPathLeft(){
var UlWidth = $(".place-input ul").width();
var SpanPathWidth = $(".place-input").width() - 20;
var Ml = UlWidth - SpanPathWidth;
if(UlWidth > SpanPathWidth ){
$(".place-input ul").css("left",-Ml)
}
else{
$(".place-input ul").css("left",0)
}
}
// $('.layui-layer-page').css('height','670px');
+2 -1
View File
@@ -80,7 +80,8 @@ innodb_data_home_dir = {$SERVER_APP_PATH}/data
innodb_data_file_path = ibdata1:10M:autoextend innodb_data_file_path = ibdata1:10M:autoextend
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
innodb_buffer_pool_size = 16M 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_log_buffer_size = 8M
innodb_flush_log_at_trx_commit = 2 innodb_flush_log_at_trx_commit = 2
innodb_lock_wait_timeout = 120 innodb_lock_wait_timeout = 120
+1 -1
View File
@@ -11,7 +11,7 @@
"path": "server/mysql/VERSION", "path": "server/mysql/VERSION",
"todo_versions":["5.6","5.7","8.0"], "todo_versions":["5.6","5.7","8.0"],
"versions":["5.5", "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", "shell":"install.sh",
"checks":"server/mysql", "checks":"server/mysql",
"path":"server/mysql", "path":"server/mysql",
+4 -4
View File
@@ -17,7 +17,7 @@ sysName=`uname`
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
mysqlDir=${serverPath}/source/mysql mysqlDir=${serverPath}/source/mysql
VERSION="5.7.39" VERSION=5.7.39
Install_mysql() Install_mysql()
@@ -64,11 +64,11 @@ Install_mysql()
cd ${rootPath}/plugins/mysql/lib && /bin/bash rpcgen.sh cd ${rootPath}/plugins/mysql/lib && /bin/bash rpcgen.sh
if [ ! -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then 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 fi
#检测文件是否损坏. #检测文件是否损坏.
md5_mysql_ok=db1b672fc257bd46356c7af26dd22801 md5_mysql_ok=d949b0ef81c3f52f7ef0874066244221
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'` md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then
@@ -76,7 +76,7 @@ Install_mysql()
else else
# 重新下载 # 重新下载
rm -rf ${mysqlDir}/mysql-${VERSION} 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
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_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() Install_mysql()
{ {
mkdir -p ${mysqlDir} mkdir -p ${mysqlDir}
@@ -107,11 +107,11 @@ Install_mysql()
fi fi
if [ ! -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then 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 fi
#检测文件是否损坏. #检测文件是否损坏.
md5_mysql_ok=362b8141ecaf425b803fe55292e2df98 md5_mysql_ok=313d625fcaa932bd87b48f0cf9b40f1c
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'` md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then
@@ -119,7 +119,7 @@ Install_mysql()
else else
# 重新下载 # 重新下载
rm -rf ${mysqlDir}/mysql-${VERSION} 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
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 waf_limit 30m;
lua_shared_dict drop_ip 10m; lua_shared_dict waf_drop_ip 10m;
lua_shared_dict drop_sum 10m; lua_shared_dict waf_drop_sum 10m;
lua_package_path "{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;"; 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; access_by_lua_file {$WAF_PATH}/lua/init.lua;
#init_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;
+16 -2
View File
@@ -1,4 +1,18 @@
<style> <style>
.overflow_hide {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
display: inline-block;
vertical-align: middle;
}
.cur {
background-color: #20a53a;
color: #fff;
}
/*waf*/ /*waf*/
.lib-con-title { .lib-con-title {
height: 26px; height: 26px;
@@ -231,8 +245,8 @@
<p onclick="wafScreen();">首页</p> <p onclick="wafScreen();">首页</p>
<p onclick="wafGloabl();">全局配置</p> <p onclick="wafGloabl();">全局配置</p>
<p onclick="wafSite();">站点配置</p> <p onclick="wafSite();">站点配置</p>
<p onclick="wafHistory();">封锁历史</p> <p onclick="wafLogs();">封锁历史</p>
<p onclick="wafLogs();">操作日志</p> <!-- <p onclick="wafOpLogs();">操作日志</p> -->
</div> </div>
<!-- lib-con --> <!-- lib-con -->
<div class="bt-w-con pd15"> <div class="bt-w-con pd15">
+270 -26
View File
@@ -52,11 +52,50 @@ def checkArgs(data, ck=[]):
return (True, mw.returnJson(True, 'ok')) 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(): def getConf():
path = mw.getServerDir() + "/openresty/nginx/conf/nginx.conf" path = mw.getServerDir() + "/openresty/nginx/conf/nginx.conf"
return path 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(): def initDomainInfo():
data = [] data = []
path_domains = getJsonPath('domains') path_domains = getJsonPath('domains')
@@ -107,7 +146,7 @@ def initSiteInfo():
site_contents_new[name] = site_contents[name] site_contents_new[name] = site_contents[name]
else: else:
tmp = {} tmp = {}
tmp['cdn'] = False tmp['cdn'] = True
tmp['log'] = True tmp['log'] = True
tmp['get'] = True tmp['get'] = True
tmp['post'] = True tmp['post'] = True
@@ -120,6 +159,7 @@ def initSiteInfo():
tmp['user-agent'] = config_contents['user-agent'] tmp['user-agent'] = config_contents['user-agent']
tmp['cookie'] = config_contents['cookie'] tmp['cookie'] = config_contents['cookie']
tmp['scan'] = config_contents['scan'] tmp['scan'] = config_contents['scan']
tmp['safe_verify'] = config_contents['safe_verify']
cdn_header = ['x-forwarded-for', cdn_header = ['x-forwarded-for',
'x-real-ip', 'x-real-ip',
@@ -132,7 +172,6 @@ def initSiteInfo():
'cdn-src-ip', 'cdn-src-ip',
'cdn-real-ip', 'cdn-real-ip',
'cf-connecting-ip', 'cf-connecting-ip',
'cf-connecting-ip',
'x-cluster-client-ip', 'x-cluster-client-ip',
'wl-proxy-client-ip', 'wl-proxy-client-ip',
'proxy-client-ip', 'proxy-client-ip',
@@ -178,7 +217,9 @@ def initTotalInfo():
tmp['get'] = 0 tmp['get'] = 0
tmp['post'] = 0 tmp['post'] = 0
tmp['total'] = 0 tmp['total'] = 0
tmp['url_ext'] = 0 tmp['path'] = 0
tmp['php_path'] = 0
tmp['upload_ext'] = 0
_name = {} _name = {}
_name[name] = tmp _name[name] = tmp
total_contents['sites'] = _name total_contents['sites'] = _name
@@ -211,10 +252,89 @@ def contentReplace(content):
return content return content
def autoMakeLuaConfSingle(file):
# path = getPluginDir() + "/waf/rule/" + file + ".json"
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',
'url_white', '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(): def initDreplace():
path = getServerDir() path = getServerDir()
if not os.path.exists(path + '/waf'): if not os.path.exists(path + '/waf/lua'):
sdir = getPluginDir() + '/waf' sdir = getPluginDir() + '/waf'
cmd = 'cp -rf ' + sdir + ' ' + path cmd = 'cp -rf ' + sdir + ' ' + path
mw.execShell(cmd) mw.execShell(cmd)
@@ -245,6 +365,11 @@ def initDreplace():
content = contentReplace(content) content = contentReplace(content)
mw.writeFile(config_common, 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_conf = mw.getServerDir() + "/openresty/nginx/conf/luawaf.conf"
waf_tpl = getPluginDir() + "/conf/luawaf.conf" waf_tpl = getPluginDir() + "/conf/luawaf.conf"
content = mw.readFile(waf_tpl) content = mw.readFile(waf_tpl)
@@ -254,6 +379,10 @@ def initDreplace():
initDomainInfo() initDomainInfo()
initSiteInfo() initSiteInfo()
initTotalInfo() initTotalInfo()
autoMakeLuaConf()
initDefaultInfo()
pSqliteDb()
if not mw.isAppleSystem(): if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + path) mw.execShell("chown -R www:www " + path)
@@ -267,6 +396,9 @@ def start():
conf = conf.replace('#include luawaf.conf;', "include luawaf.conf;") conf = conf.replace('#include luawaf.conf;', "include luawaf.conf;")
mw.writeFile(path, conf) mw.writeFile(path, conf)
import tool_task
tool_task.createBgTask()
mw.restartWeb() mw.restartWeb()
return 'ok' return 'ok'
@@ -277,6 +409,10 @@ def stop():
conf = conf.replace('include luawaf.conf;', "#include luawaf.conf;") conf = conf.replace('include luawaf.conf;', "#include luawaf.conf;")
mw.writeFile(path, conf) mw.writeFile(path, conf)
import tool_task
tool_task.removeBgTask()
mw.restartWeb() mw.restartWeb()
return 'ok' return 'ok'
@@ -288,8 +424,19 @@ def restart():
def reload(): def reload():
stop() stop()
mw.execShell('rm -rf ' + mw.getServerDir() +
"/openresty/nginx/logs/error.log") path = getServerDir()
path_tpl = getPluginDir()
config = path + "/waf/lua/init.lua"
config_tpl = path_tpl + "/waf/lua/init.lua"
content = mw.readFile(config_tpl)
content = contentReplace(content)
mw.writeFile(config, content)
errlog = mw.getServerDir() + "/openresty/nginx/logs/error.log"
mw.execShell('rm -rf ' + errlog)
start() start()
return 'ok' return 'ok'
@@ -340,7 +487,7 @@ def addRule():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(fpath, cjson) mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content) return mw.returnJson(True, '设置成功!', content)
@@ -362,7 +509,7 @@ def removeRule():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(fpath, cjson) mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content) return mw.returnJson(True, '设置成功!', content)
@@ -387,7 +534,7 @@ def setRuleState():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(fpath, cjson) mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content) return mw.returnJson(True, '设置成功!', content)
@@ -418,7 +565,7 @@ def modifyRule():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(fpath, cjson) mw.writeFile(fpath, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', content) return mw.returnJson(True, '设置成功!', content)
@@ -459,6 +606,7 @@ def addSiteRule():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -494,6 +642,7 @@ def addIpWhite():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -514,6 +663,8 @@ def removeIpWhite():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -549,6 +700,8 @@ def addIpBlack():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -569,6 +722,8 @@ def removeIpBlack():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -587,6 +742,7 @@ def setIpv6Black():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -603,9 +759,10 @@ def delIpv6Black():
content = json.loads(content) content = json.loads(content)
content.remove(addr) content.remove(addr)
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -628,6 +785,8 @@ def removeSiteRule():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -642,11 +801,13 @@ def setObjStatus():
cobj = json.loads(content) cobj = json.loads(content)
o = args['obj'] o = args['obj']
status = args['statusCode'] status = int(args['statusCode'])
cobj[o]['status'] = status cobj[o]['status'] = status
cjson = mw.getJson(cobj) cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson) mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -666,6 +827,32 @@ def setRetry():
cjson = mw.getJson(cobj) cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson) 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, '设置成功!', []) return mw.returnJson(True, '设置成功!', [])
@@ -676,7 +863,7 @@ def setSiteRetry():
def setCcConf(): def setCcConf():
args = getArgs() args = getArgs()
data = checkArgs(args, ['siteName', 'cycle', 'limit', data = checkArgs(args, ['siteName', 'cycle', 'limit',
'endtime', 'is_open_global', 'increase']) 'endtime', 'is_open_global'])
if not data[0]: if not data[0]:
return data[1] return data[1]
@@ -695,6 +882,8 @@ def setCcConf():
cjson = mw.getJson(cobj) cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson) mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', []) return mw.returnJson(True, '设置成功!', [])
@@ -711,6 +900,8 @@ def saveScanRule():
path = getRuleJsonPath('scan_black') path = getRuleJsonPath('scan_black')
cjson = mw.getJson(args) cjson = mw.getJson(args)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!', []) return mw.returnJson(True, '设置成功!', [])
@@ -750,6 +941,26 @@ def getSiteConfig():
return mw.returnJson(True, 'ok!', content) 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(): def getSiteConfigByName():
args = getArgs() args = getArgs()
data = checkArgs(args, ['siteName']) data = checkArgs(args, ['siteName'])
@@ -783,6 +994,8 @@ def addSiteCdnHeader():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '添加成功!') return mw.returnJson(True, '添加成功!')
@@ -802,6 +1015,8 @@ def removeSiteCdnHeader():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '删除成功!') return mw.returnJson(True, '删除成功!')
@@ -824,29 +1039,44 @@ def importData():
path = getRuleJsonPath(args['s_Name']) path = getRuleJsonPath(args['s_Name'])
mw.writeFile(path, args['pdata']) mw.writeFile(path, args['pdata'])
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
def getLogsList(): def getLogsList():
args = getArgs() args = getArgs()
data = checkArgs(args, ['siteName']) data = checkArgs(args, ['site', 'page', 'page_size', 'tojs'])
if not data[0]: if not data[0]:
return data[1] return data[1]
data = [] page = int(args['page'])
path = getServerDir() + '/logs' page_size = int(args['page_size'])
domain = args['site']
tojs = args['tojs']
if not os.path.exists(path): conn = pSqliteDb('logs')
return mw.returnJson(False, '还未生成!', [])
files = os.listdir(path) field = 'time,ip,domain,server_name,method,uri,user_agent,rule_name,reason'
for f in files: limit = str(page_size) + ' offset ' + str(page_size * (page - 1))
if f == '.DS_Store':
continue condition = ''
f = f.split('_') conn = conn.field(field)
if f[0] == args['siteName']: conn = conn.where("1=1", ()).where("domain=?", (domain,))
fl = f[1].split('.')
data.append(fl[0]) 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) return mw.returnJson(True, 'ok!', data)
@@ -893,6 +1123,7 @@ def setObjOpen():
cjson = mw.getJson(cobj) cjson = mw.getJson(cobj)
mw.writeFile(conf, cjson) mw.writeFile(conf, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -922,6 +1153,7 @@ def setSiteObjOpen():
cjson = mw.getJson(content) cjson = mw.getJson(content)
mw.writeFile(path, cjson) mw.writeFile(path, cjson)
restartWeb()
return mw.returnJson(True, '设置成功!') return mw.returnJson(True, '设置成功!')
@@ -942,6 +1174,12 @@ def installPreInspection():
return 'ok' 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__": if __name__ == "__main__":
func = sys.argv[1] func = sys.argv[1]
if func == 'status': if func == 'status':
@@ -998,12 +1236,16 @@ if __name__ == "__main__":
print(setSiteCcConf()) print(setSiteCcConf())
elif func == 'set_retry': elif func == 'set_retry':
print(setRetry()) print(setRetry())
elif func == 'set_safe_verify':
print(setSafeVerify())
elif func == 'set_site_retry': elif func == 'set_site_retry':
print(setSiteRetry()) print(setSiteRetry())
elif func == 'save_scan_rule': elif func == 'save_scan_rule':
print(saveScanRule()) print(saveScanRule())
elif func == 'get_site_config': elif func == 'get_site_config':
print(getSiteConfig()) print(getSiteConfig())
elif func == 'get_default_site':
print(getDefaultSite())
elif func == 'get_site_config_byname': elif func == 'get_site_config_byname':
print(getSiteConfigByName()) print(getSiteConfigByName())
elif func == 'add_site_cdn_header': elif func == 'add_site_cdn_header':
@@ -1024,5 +1266,7 @@ if __name__ == "__main__":
print(getWafConf()) print(getWafConf())
elif func == 'waf_site': elif func == 'waf_site':
print(getWafSite()) print(getWafSite())
elif func == 'clean_drop_ip':
print(cleanDropIp())
else: else:
print('error') print('error')
+1 -1
View File
@@ -11,5 +11,5 @@
"home":"https://github.com/loveshell/ngx_lua_waf", "home":"https://github.com/loveshell/ngx_lua_waf",
"date":"2019-04-21", "date":"2019-04-21",
"pid": "1", "pid": "1",
"versions": ["0.1"] "versions": ["0.2.3"]
} }
+74 -6
View File
@@ -7,31 +7,99 @@ rootPath=$(dirname "$curPath")
rootPath=$(dirname "$rootPath") rootPath=$(dirname "$rootPath")
serverPath=$(dirname "$rootPath") serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl 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(){ Install_of(){
echo '正在安装脚本文件...' > $install_tmp echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source/op_waf
mkdir -p $serverPath/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 echo 'install ok' > $install_tmp
cd ${rootPath} && python3 ${rootPath}/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(){ Uninstall_of(){
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py stop cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py stop
rm -rf $serverPath/op_waf if [ "$?" == "0" ];then
rm -rf $serverPath/op_waf
fi
} }
action=$1
type=$2
action=$1 action=$1
if [ "${1}" == 'install' ];then if [ "${1}" == 'install' ];then
Install_of Install_of
+369 -199
View File
@@ -69,8 +69,10 @@ function setObjOpen(ruleName){
owPost('set_obj_open', {obj:ruleName},function(data){ owPost('set_obj_open', {obj:ruleName},function(data){
var rdata = $.parseJSON(data.data); var rdata = $.parseJSON(data.data);
if (rdata.status){ 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 { } else {
layer.msg('设置失败!',{icon:0,time:2000,shade: [0.3, '#000']}); layer.msg('设置失败!',{icon:0,time:2000,shade: [0.3, '#000']});
} }
@@ -84,7 +86,7 @@ function saveCcRule(siteName,is_open_global, type) {
if(type == 2){ if(type == 2){
// set_aicc_open('start'); // set_aicc_open('start');
increase = "0"; increase = "0";
}else{ } else {
// set_aicc_open('stop'); // set_aicc_open('stop');
increase = type; increase = type;
} }
@@ -164,7 +166,10 @@ function setCcRule(cycle, limit, endtime, siteName, increase){
<li>请不要设置过于严格的CC规则,以免影响正常用户体验</li>\ <li>请不要设置过于严格的CC规则,以免影响正常用户体验</li>\
<li><font style="color:red;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用:全局设置当前CC规则,且覆盖当前全部站点的CC规则</font></li>\ <li><font style="color:red;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用:全局设置当前CC规则,且覆盖当前全部站点的CC规则</font></li>\
</ul>\ </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>', </form>',
success:function(layero,index){ success:function(layero,index){
$('.btn_cc_all').click(function(){ $('.btn_cc_all').click(function(){
@@ -201,9 +206,12 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
</div>\ </div>\
<ul class="help-info-text c7 ptb10">\ <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;">'+ 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>\ </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>', </form>',
success:function(){ success:function(){
$('.btn_retry_all').click(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规则 //保存retry规则
function saveRetry(siteName,type) { function saveRetry(siteName,type) {
var pdata = { var pdata = {
@@ -253,15 +320,6 @@ function addRule(ruleName) {
},1000); },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) { function modifyRule(index, ruleName) {
@@ -633,6 +691,71 @@ function ipWhite(type) {
}); });
} }
//IP白名单
function urlWhite(type) {
var ruleName = "url_white";
if (type == undefined) {
create_l = layer.open({
type: 1,
title: "管理URL白名单",
area: ['700px', '530px'],
closeBtn: 1,
shadeClose: false,
content: '<div class="pd15">\
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
<input class="bt-input-text" name="ruleValue" type="text" value="" style="width:470px;margin-right:12px;" placeholder="规则内容,请使用正则表达式">\
<input class="bt-input-text mr5" name="rulePs" type="text" style="width:120px;" placeholder="描述">\
<button class="btn btn-success btn-sm va0 pull-right" onclick="addRule(\''+ ruleName + '\');">添加</button>\</div>\
<div class="divtable">\
<div id="jc-file-table" class="table_head_fix" style="max-height:300px;overflow:auto;border:#ddd 1px solid">\
<table class="table table-hover" style="border:none">\
<thead>\
<tr>\
<th width="360">规则</th>\
<th>说明</th>\
<th>操作</th>\
<th style="text-align: right;">状态</th>\
</tr>\
</thead>\
<tbody id="set_obj_conf_con" class="gztr"></tbody>\
</table>\
</div>\
</div>\
<ul class="help-info-text c7 ptb10">\
<li style="color:red;">注意:如果您不了解正则表达式,请不要随意修改规则内容</li>\
<li>您可以添加或修改规则内容,但请使用正则表达式</li>\
<li>内置规则允许修改,但不可以直接删除,您可以设置规则状态来定义防火墙是否使用此规则</li>\
</ul></div>'
});
tableFixed("jc-file-table");
}
getRuleByName(ruleName, function(data){
var tmp = $.parseJSON(data.data);
var rdata = $.parseJSON(tmp.data);
console.log(rdata);
var tbody = ''
for (var i = 0; i < rdata.length; i++) {
var removeRule = ''
if (rdata[i][3] != 0) removeRule = ' | <a class="btlink" onclick="removeRule(\'' + ruleName + '\',' + i + ')">删除</a>';
tbody += '<tr>\
<td class="rule_body_'+ i + '">' + rdata[i][1] + '</td>\
<td class="rule_ps_'+ i + '">' + rdata[i][2] + '</td>\
<td class="rule_modify_'+ i + '"><a class="btlink" onclick="modifyRule(' + i + ',\'' + ruleName + '\')">编辑</a>' + removeRule + '</td>\
<td class="text-right">\
<div class="pull-right">\
<input class="btswitch btswitch-ios" id="closeua_'+ i + '" type="checkbox" ' + (rdata[i][0] ? 'checked' : '') + '>\
<label class="btswitch-btn" style="width:2.0em;height:1.2em;margin-bottom: 0" for="closeua_'+ i + '" onclick="setRuleState(\'' + ruleName + '\',' + i + ')"></label>\
</div>\
</td>\
</tr>'
}
$("#set_obj_conf_con").html(tbody);
});
}
// 获取IPV4黑名单 // 获取IPV4黑名单
function getIpv4Address(callback){ function getIpv4Address(callback){
@@ -695,6 +818,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段 //从IP黑名单删除IP段
function removeIpBlack(index) { function removeIpBlack(index) {
@@ -820,17 +960,17 @@ function wafScreen(){
con += '<div class="screen">\ 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">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">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">恶意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">Cookie渗透</span><span class="val">'+rdata.rules.cookie+'</span></div>\
<div class="line"><span class="name">恶意扫描</span><span class="val">'+rdata.rules.scan+'</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">恶意HEAD请求</span><span class="val">0</span></div>\
<div class="line"><span class="name">URI自定义拦截</span><span class="val">'+rdata.rules.args+'</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">URI保护</span><span class="val">'+rdata.rules.args+'</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.upload_ext+'</span></div>\
<div class="line"><span class="name">禁止的扩展名</span><span class="val">'+rdata.rules.url_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">0</span></div>\ <div class="line"><span class="name">禁止PHP脚本</span><span class="val">'+rdata.rules.php_path+'</span></div>\
</div>'; </div>';
con += '<div style="width:660px;"><ul class="help-info-text c7">\ con += '<div style="width:660px;"><ul class="help-info-text c7">\
@@ -878,6 +1018,16 @@ function wafGloabl(){
<td style="text-align: center;">--</td>\ <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>\ <td class="text-right"><a class="btlink" onclick="setRetry('+ rdata.retry.retry_cycle + ',' + rdata.retry.retry + ',' + rdata.retry.retry_time + ')">初始规则</a></td>\
</tr>\ </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>\ <tr>\
<td>GET-URI过滤</td>\ <td>GET-URI过滤</td>\
<td>'+ rdata.get.ps + '</td>\ <td>'+ rdata.get.ps + '</td>\
@@ -918,6 +1068,11 @@ function wafGloabl(){
<label class="btswitch-btn" for="closescan" onclick="setObjOpen(\'scan\')"></label>\ <label class="btswitch-btn" for="closescan" onclick="setObjOpen(\'scan\')"></label>\
</div></td><td class="text-right"><a class="btlink" onclick="scanRule()">设置</a></td>\ </div></td><td class="text-right"><a class="btlink" onclick="scanRule()">设置</a></td>\
</tr>\ </tr>\
<tr>\
<td>URL白名单</td><td>所有规则对URL白名单无效</td><td style="text-align: center;">--</td>\
<td style="text-align: center;">--</td>\
<td class="text-right"><a class="btlink" onclick="urlWhite()">设置</a></td>\
</tr>\
<tr>\ <tr>\
<td>IP白名单</td><td>所有规则对IP白名单无效</td><td style="text-align: center;">--</td>\ <td>IP白名单</td><td>所有规则对IP白名单无效</td><td style="text-align: center;">--</td>\
<td style="text-align: center;">--</td>\ <td style="text-align: center;">--</td>\
@@ -940,7 +1095,7 @@ function wafGloabl(){
con += '<div style="width:645px;margin-top:10px;"><ul class="help-info-text c7">\ con += '<div style="width:645px;margin-top:10px;"><ul class="help-info-text c7">\
<li>继承: 全局设置将在站点配置中自动继承为默认值</li>\ <li>继承: 全局设置将在站点配置中自动继承为默认值</li>\
<li>优先级: IP白名单>IP黑名单>URL白名单>URL黑名单>CC防御>禁止国外IP访问>User-Agent>URI过滤>URL参数>Cookie>POST</li>\ <li>优先级: IP白名单>IP黑名单>URL白名单>URL黑名单>CC防御>User-Agent>URI过滤>URL参数>Cookie>POST</li>\
</ul></div>'; </ul></div>';
$(".soft-man-con").html(con); $(".soft-man-con").html(con);
}); });
@@ -956,146 +1111,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: 1,
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: 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>'+ 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) { function html_encode(value) {
return $('<div></div>').html(value).text(); return $('<div></div>').html(value).text();
} }
@@ -1543,7 +1558,6 @@ function siteWafConfig(siteName, type) {
function wafSite(){ function wafSite(){
owPost('get_site_config', {}, function(data){ owPost('get_site_config', {}, function(data){
var tmp = $.parseJSON(data.data); var tmp = $.parseJSON(data.data);
var rdata = $.parseJSON(tmp.data); var rdata = $.parseJSON(tmp.data);
@@ -1553,32 +1567,20 @@ function wafSite(){
i += 1; i += 1;
tbody += '<tr>\ tbody += '<tr>\
<td><a onclick="siteWafConfig(\''+ k + '\')" class="sitename btlink" title="' + k + '">' + k + '</a></td>\ <td><a onclick="siteWafConfig(\''+ k + '\')" class="sitename btlink" title="' + k + '">' + k + '</a></td>\
<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>\
<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><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>\ <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>\ <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>\
<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><input onclick="setSiteObjState(\''+ k + '\',\'cdn\')" type="checkbox" ' + (v.cdn ? 'checked' : '') + '></td>\
</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 + '\',\'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>\ <td>\
<div class="ssh-item" style="margin-left:0">\ <div class="ssh-item" style="margin-left:0">\
<input class="btswitch btswitch-ios" id="closeget_'+ i + '" type="checkbox" ' + (v.open ? 'checked' : '') + '>\ <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>\ <label class="btswitch-btn" for="closeget_'+ i + '" onclick="setSiteObjState(\'' + k + '\',\'open\')"></label>\
</div>\ </div>\
</td>\ </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>\ <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>' </tr>';
}); });
var con = '<div class="lib-box">\ var con = '<div class="lib-box">\
@@ -1612,27 +1614,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">\ var con = '<div class="divtable">\
<table class="table table-hover waftable" style="color:#fff;">\ <table class="table table-hover waftable" style="color:#fff;">\
<thead><tr><th width="18%">名称</th>\ <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)
+160 -6
View File
@@ -23,6 +23,17 @@ TEST_URL = "http://t1.cn/"
# TEST_URL = "https://www.zzzvps.com/" # 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): def httpGet(url, timeout=10):
import urllib.request import urllib.request
@@ -35,6 +46,61 @@ def httpGet(url, timeout=10):
return str(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): def httpGet__UA(url, ua, timeout=10):
import urllib.request import urllib.request
headers = {'user-agent': ua} headers = {'user-agent': ua}
@@ -48,6 +114,19 @@ def httpGet__UA(url, ua, timeout=10):
return str(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): def httpPost(url, data, timeout=10):
""" """
发送POST请求 发送POST请求
@@ -94,7 +173,7 @@ def test_Dir():
url = TEST_URL + '?t=../etc/passwd' url = TEST_URL + '?t=../etc/passwd'
print("args test start") print("args test start")
url_val = httpGet(url, 10) url_val = httpGet(url, 10)
# print(url_val) print(url_val)
print("args test end") print("args test end")
@@ -109,6 +188,43 @@ def test_UA():
print("user-agent test end") 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(): def test_POST():
''' '''
user-agent 过滤 user-agent 过滤
@@ -125,7 +241,7 @@ def test_scan():
''' '''
目录保存 目录保存
''' '''
url = TEST_URL + '/acunetix_wvs_security_test?t=1' url = TEST_URL + 'acunetix_wvs_security_test?t=1'
print("scan test start") print("scan test start")
url_val = httpGet(url, 10) url_val = httpGet(url, 10)
print(url_val) print(url_val)
@@ -158,16 +274,54 @@ def test_url_ext():
print("url_ext end") 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(): def test_start():
# test_OK()
# test_Dir() # test_Dir()
# test_UA() # test_UA()
# test_POST() test_Header()
# test_scan() # test_UA_for(1000)
test_POST()
test_scan()
# test_CC() # test_CC()
test_url_ext() # test_url_ext()
# test_cdn()
# test_Upload()
if __name__ == "__main__": if __name__ == "__main__":
os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/op_waf && sh install.sh uninstall 0.1 && sh install.sh install 0.1') 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') os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/ && python3 plugins/openresty/index.py stop && python3 plugins/openresty/index.py start')
test_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
```
+16 -3
View File
@@ -2,8 +2,21 @@
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH export PATH
# apt -y install apache2-utils
# yum -y install httpd-tools # yum -y install httpd-tools
# ab -c 1000 -n 1000000 http://xx.xx.xx/
# 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 python3 index.py
+16 -7
View File
@@ -52,7 +52,7 @@ def createBgTask():
removeBgTask() removeBgTask()
args = { args = {
"period": "minute-n", "period": "minute-n",
"minute-n": "3", "minute-n": "1",
} }
createBgTaskByName(getPluginName(), args) createBgTaskByName(getPluginName(), args)
@@ -71,7 +71,7 @@ def createBgTaskByName(name, args):
print("计划任务已经存在!") print("计划任务已经存在!")
return True return True
import crontab_api import crontab_api
api = crontab_api.crontab_api() cron_api = crontab_api.crontab_api()
period = args['period'] period = args['period']
_hour = '' _hour = ''
@@ -87,16 +87,18 @@ def createBgTaskByName(name, args):
_where1 = args['minute-n'] _where1 = args['minute-n']
_minute = '' _minute = ''
mw_dir = mw.getRunDir()
cmd = ''' cmd = '''
mw_dir=%s
rname=%s rname=%s
plugin_path=%s plugin_path=%s
script_path=%s script_path=%s
logs_file=$plugin_path/${rname}.log logs_file=$plugin_path/${rname}.log
''' % (name, getServerDir(), getPluginDir()) ''' % (mw_dir, name, getServerDir(), getPluginDir())
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n" cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n" cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
cmd += 'echo "python3 $script_path/tool_task.py run >> $logs_file 2>&1"' + "\n" cmd += 'echo "cd $mw_dir && source bin/activate && python3 $script_path/tool_task.py run >> $logs_file 2>&1"' + "\n"
cmd += '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 "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n" cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
@@ -115,7 +117,7 @@ logs_file=$plugin_path/${rname}.log
'urladdress': '', 'urladdress': '',
} }
task_id = api.add(params) task_id = cron_api.add(params)
if task_id > 0: if task_id > 0:
cfg["task_id"] = task_id cfg["task_id"] = task_id
cfg["name"] = name cfg["name"] = name
@@ -144,8 +146,15 @@ def removeBgTask():
return False return False
def getCpuUsed():
import psutil
used = psutil.cpu_percent(interval=1)
path = getServerDir() + "/cpu.info"
mw.writeFile(path, str(int(used)))
def run(): def run():
print('op lua run ok') getCpuUsed()
if __name__ == "__main__": if __name__ == "__main__":
if len(sys.argv) > 1: if len(sys.argv) > 1:
+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/waf", "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} *{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"} body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;} .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} .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;} .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} .t2{margin-bottom:8px; font-weight:bold}
+1 -1
View File
@@ -7,7 +7,7 @@
*{margin:0;padding:0;color:#444} *{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"} body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;} .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} .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;} .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} .t2{margin-bottom:8px; font-weight:bold}
+1 -1
View File
@@ -7,7 +7,7 @@
*{margin:0;padding:0;color:#444} *{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"} body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;} .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} .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;} .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} .t2{margin-bottom:8px; font-weight:bold}
+1 -1
View File
@@ -7,7 +7,7 @@
*{margin:0;padding:0;color:#444} *{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"} body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;} .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} .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;} .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} .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} *{margin:0;padding:0;color:#444}
body{font-size:14px;font-family:"宋体"} body{font-size:14px;font-family:"宋体"}
.main{width:600px;margin:10% auto;} .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} .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;} .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} .t2{margin-bottom:8px; font-weight:bold}
+372 -192
View File
@@ -4,33 +4,187 @@ local _M = { _VERSION = '0.02' }
local mt = { __index = _M } local mt = { __index = _M }
local json = require "cjson" local json = require "cjson"
local ngx_match = ngx.re.find local sqlite3 = require "lsqlite3"
local ngx_match = ngx.re.find
local debug_mode = false local debug_mode = false
local waf_root = "{$WAF_ROOT}" local waf_root = "{$WAF_ROOT}"
local cpath = waf_root.."/waf/" local cpath = waf_root.."/waf/"
local logdir = waf_root.."/logs/" local log_dir = waf_root.."/logs/"
local rpath = cpath.."/rule/" local rpath = cpath.."/rule/"
function _M.new(self) function _M.new(self)
local self = { local self = {
waf_root = waf_root, waf_root = waf_root,
cpath = cpath, cpath = cpath,
rpath = rpath, rpath = rpath,
logdir = logdir, logdir = log_dir,
config = '', config = '',
site_config = '', site_config = '',
server_name = '', server_name = '',
params = nil global_tatal = nil,
params = nil,
} }
return setmetatable(self, mt) return setmetatable(self, mt)
end 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()
db:exec([[BEGIN TRANSACTION]])
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)]]
if not stmt2 then
self:D("waf timer db:prepare fail!:"..tostring(stmt2))
return false
end
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) function _M.setDebug(self, mode)
debug_mode = mode debug_mode = mode
end end
@@ -38,7 +192,6 @@ end
-- 调试方式 -- 调试方式
function _M.D(self, msg) function _M.D(self, msg)
if not debug_mode then return true end if not debug_mode then return true end
local _msg = '' local _msg = ''
@@ -60,7 +213,8 @@ function _M.D(self, msg)
return nil return nil
end end
local localtime = os.date("%Y-%m-%d %H:%M:%S") -- local localtime = os.date("%Y-%m-%d %H:%M:%S")
local localtime = ngx.localtime()
if server_name then if server_name then
fp:write(tostring(_msg) .. "\n") fp:write(tostring(_msg) .. "\n")
else else
@@ -72,6 +226,24 @@ function _M.D(self, msg)
return true return true
end 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) local function write_file_clear(filename, body)
fp = io.open(filename,'w') fp = io.open(filename,'w')
@@ -127,11 +299,11 @@ function _M.is_max(self,ip1,ip2)
end end
function _M.split(self, str,reps ) function _M.split(self, str,reps )
local resultStrList = {} local rsList = {}
string.gsub(str,'[^'..reps..']+',function(w) string.gsub(str,'[^'..reps..']+',function(w)
table.insert(resultStrList,w) table.insert(rsList,w)
end) end)
return resultStrList return rsList
end end
function _M.arrip(self, ipstr) function _M.arrip(self, ipstr)
@@ -157,32 +329,41 @@ function _M.compare_ip(self,ips)
end end
function _M.to_json(self, msg) function _M.to_json(self, msg)
return json.encode(msg) return json.encode(msg)
end end
function _M.return_message(self, status, msg) function _M.return_state(status,msg)
ngx.header.content_type = "application/json;" result = {}
ngx.status = status result['status'] = status
ngx.say(json.encode(msg)) result['msg'] = msg
ngx.exit(status) return result
end end
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) function _M.return_html(self, status, html)
ngx.header.content_type = "text/html" ngx.header.content_type = "text/html"
ngx.status = status status = tonumber(status)
ngx.say(html) -- self:D("return_html:"..tostring(status))
if status == 200 then
ngx.say(html)
end
ngx.exit(status) ngx.exit(status)
end end
function _M.read_file_body(self, filename) function _M.read_file_body(self, filename)
-- ngx.log(ngx.ERR,"read_file_body:"..filename)
fp = io.open(filename, 'r') fp = io.open(filename, 'r')
if fp == nil then if fp == nil then
return nil return nil
end end
fbody = fp:read("*a") local fbody = fp:read("*a")
fp:close() fp:close()
if fbody == '' then if fbody == '' then
return nil return nil
@@ -190,7 +371,38 @@ function _M.read_file_body(self, filename)
return fbody return fbody
end 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) function _M.write_file(self, filename, body)
fp = io.open(filename,'ab') fp = io.open(filename,'ab')
@@ -203,30 +415,10 @@ function _M.write_file(self, filename, body)
return true return true
end end
function _M.write_file_clear(self, filename, body) function _M.write_file_clear(self, filename, body)
return write_file_clear(filename, body) return write_file_clear(filename, body)
end end
function _M.write_drop_ip(self, is_drop, drop_time)
local filename = self.logdir .. '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) function _M.write_to_file(self, logstr)
local server_name = self.params['server_name'] local server_name = self.params['server_name']
local filename = self.logdir .. '/' .. server_name .. '_' .. ngx.today() .. '.log' local filename = self.logdir .. '/' .. server_name .. '_' .. ngx.today() .. '.log'
@@ -234,10 +426,19 @@ function _M.write_to_file(self, logstr)
return true return true
end 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) function _M.continue_key(self,key)
key = tostring(key) key = tostring(key)
if string.len(key) > 64 then return false end; 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) for _,k in ipairs(keys)
do do
if k == key then return false end; if k == key then return false end;
@@ -257,7 +458,7 @@ function _M.array_len(self, arr)
end end
function _M.is_ipaddr(self, client_ip) 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 if self:array_len(cipn) < 4 then return false end
for _,v in ipairs({1,2,3,4}) for _,v in ipairs({1,2,3,4})
do do
@@ -268,58 +469,29 @@ function _M.is_ipaddr(self, client_ip)
return true return true
end end
-- 定时异步同步统计信息
function _M.read_file_body_decode(self, filename) function _M.timer_stats_total(self)
return json.decode(self:read_file_body(filename)) local total_path = self.cpath .. 'total.json'
end local total = ngx.shared.waf_limit:get(total_path)
if not total then
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(name))
end
local function timer_at_inc_log(premature)
local total_path = cpath .. 'total.json'
local tbody = ngx.shared.limit:get(total_path)
if not tbody then
return false return false
end end
return write_file_clear(total_path,tbody) return self:write_file_clear(total_path,total)
end end
function _M.inc_log(self, name, rule) function _M.stats_total(self, name, rule)
local server_name = self.params['server_name'] local server_name = self.params['server_name']
local total_path = self.cpath .. 'total.json' local total_path = cpath .. 'total.json'
local tbody = ngx.shared.limit:get(total_path) local total = ngx.shared.waf_limit:get(total_path)
if not tbody then
tbody = self:read_file_body(total_path) if not total then
if not tbody then return false end local tbody = self:read_file_body(total_path)
total = json.decode(tbody)
else
total = json.decode(total)
end end
local total = json.decode(tbody) if not total then return false end
-- 开始计算 -- 开始计算
if not total['sites'] then total['sites'] = {} end if not total['sites'] then total['sites'] = {} end
@@ -332,43 +504,55 @@ function _M.inc_log(self, name, rule)
total['sites'][server_name][name] = total['sites'][server_name][name] + 1 total['sites'][server_name][name] = total['sites'][server_name][name] + 1
total['rules'][name] = total['rules'][name] + 1 total['rules'][name] = total['rules'][name] + 1
local total_log = json.encode(total) ngx.shared.waf_limit:set(total_path,json.encode(total))
if not total_log then return false end
ngx.shared.limit:set(total_path,total_log)
-- 异步执行 -- 异步执行
ngx.timer.at(1, timer_at_inc_log) -- 现在改再init_workder.lua 定时执行
-- ngx.timer.every(3, timer_stats_total_log)
end 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) for _,v in ipairs(config_domains)
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)
do do
for _,d_name in ipairs(v['domains']) for _,cd_name in ipairs(v['domains'])
do do
if c_name == d_name then if request_name == cd_name then
ngx.shared.limit:set(c_name,v['name'],3600) ngx.shared.waf_limit:set(request_name,v['name'],86400)
return v['name'] return v['name']
end end
end end
end end
return c_name return "unset"
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 end
function _M.is_ngx_match_orgin(self,rule,match, sign) function _M.is_ngx_match_orgin(self,rule, match, sign)
if ngx_match(ngx.unescape_uri(match), rule,"isjo") then if ngx_match(ngx.unescape_uri(match), rule, "isjo") then
error_rule = rule .. ' >> ' .. sign .. ':' .. match error_rule = rule .. ' >> ' .. sign .. ':' .. match
return true return true
end end
@@ -386,13 +570,28 @@ function _M.ngx_match_string(self, rule, content,sign)
end end
function _M.ngx_match_list(self, rules, content) function _M.ngx_match_list(self, rules, content)
local args_type = type(content)
for i,rule in ipairs(rules) for i,rule in ipairs(rules)
do do
if rule[1] == 1 then if rule[1] == 1 then
local t = self:is_ngx_match_orgin(rule[2], content, rule[3]) if args_type == 'string' then
if t then -- self:D("string: "..tostring(rule[2])..":".. tostring(content)..":"..tostring(rule[3]))
return true local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
if t then
return true
end
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
end end
return false return false
@@ -428,115 +627,85 @@ function _M.is_ngx_match_post(self, rules, content)
end 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}
end
for k,body in pairs(sbody)
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
end
end
end
end
end
return false
end
function _M.write_log(self, name, rule) function _M.write_log(self, name, rule)
local config = self.config
local params = self.params
local ip = self.params['ip'] local ip = params['ip']
local retry = self.config['retry']['retry'] local ngx_time = ngx.time()
local retry_time = self.config['retry']['retry_time']
local retry_cycle = self.config['retry']['retry_cycle']
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 if count then
ngx.shared.drop_ip:incr(ip,1) ngx.shared.waf_drop_ip:incr(ip, 1)
else else
ngx.shared.drop_ip:set(ip,1,retry_cycle) ngx.shared.waf_drop_ip:set(ip, 1, retry_cycle)
end end
if self.config['log'] ~= true or self:is_site_config('log') ~= true then return false end if config['log'] ~= true or self:is_site_config('log') ~= true then return false end
local method = ngx.req.get_method() local method = params['method']
if error_rule then if error_rule then
rule = error_rule rule = error_rule
error_rule = nil error_rule = nil
end end
local logtmp = {ngx.localtime(), ip, method, ngx.var.request_uri, ngx.var.http_user_agent, name, rule} local count = ngx.shared.waf_drop_ip:get(ip)
local logstr = json.encode(logtmp) .. "\n" -- self:D("write_log; count:" ..tostring(count).. ",retry:" .. tostring(retry) )
local count,_ = ngx.shared.drop_ip:get(ip) if (count > retry and name ~= 'cc') then
if count > retry and name ~= 'cc' then local safe_count,_ = ngx.shared.waf_drop_sum:get(ip)
local safe_count,_ = ngx.shared.drop_sum:get(ip)
if not safe_count then 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 safe_count = 1
else else
ngx.shared.drop_sum:incr(ip,1) ngx.shared.waf_drop_sum:incr(ip, 1)
end end
local lock_time = retry_time * safe_count local lock_time = retry_time * safe_count
if lock_time > 86400 then lock_time = 86400 end 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" retry_times = retry + 1
ngx.shared.drop_ip:set(ip,retry+1,lock_time) ngx.shared.waf_drop_ip:set(ip, retry_times, lock_time)
self:write_drop_ip('inc',lock_time)
local reason = retry_cycle .. '秒以内累计超过'..retry..'次以上非法请求,封锁'.. lock_time ..'秒'
self:log(params, name, reason)
elseif name ~= 'cc' then
self:log(params, name, rule)
end end
self:write_to_file(logstr)
self:inc_log(name,rule) self:stats_total(name, rule)
end end
function _M.get_client_ip(self) function _M.get_real_ip(self, server_name)
local client_ip = "unknown" local client_ip = "unknown"
local server_name = self.params['server_name'] local site_config = self.site_config
-- self:D("fff..."..client_ip..server_name) if site_config[server_name] then
if self.site_config[server_name] then if site_config[server_name]['cdn'] then
if self.site_config[server_name]['cdn'] then local request_header = ngx.req.get_headers()
for _,v in ipairs(self.site_config[server_name]['cdn_header']) for _,v in ipairs(site_config[server_name]['cdn_header'])
do do
-- C:D("vv:"..v..tostring(request_header[v]))
if request_header[v] ~= nil and request_header[v] ~= "" then if request_header[v] ~= nil and request_header[v] ~= "" then
local header_tmp = request_header[v] local header_tmp = request_header[v]
if type(header_tmp) == "table" then header_tmp = header_tmp[1] end 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; break;
end end
end end
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 client_ip = ngx.var.remote_addr
if client_ip == nil then if client_ip == nil then
client_ip = "unknown" client_ip = "unknown"
@@ -547,11 +716,12 @@ end
function _M.is_site_config(self,cname) function _M.is_site_config(self,cname)
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 if cname == 'cc' then
return self.site_config[server_name][cname]['open'] return site_config[server_name][cname]['open']
else else
return self.site_config[server_name][cname] return site_config[server_name][cname]
end end
end end
return true return true
@@ -572,6 +742,16 @@ function _M.get_boundary(self)
end 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) function _M.return_post_data(self)
if method ~= "POST" then return false end if method ~= "POST" then return false end
content_length = tonumber(self.params["request_header"]['content-length']) content_length = tonumber(self.params["request_header"]['content-length'])
+277 -326
View File
@@ -1,153 +1,169 @@
local json = require "cjson" local json = require "cjson"
local ngx_match = ngx.re.find local ngx_match = ngx.re.find
local __C = require "common" local __WAF = require "common"
local C = __C:new()
local waf_root = "{$WAF_ROOT}" -- 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(waf_root.."/waf/"..'config.json')
local site_config = C:read_file_body_decode(waf_root.."/waf/"..'site.json')
C:setConfData(config, site_config) C:setConfData(config, site_config)
C:setDebug(true)
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"
local cookie_html = require "html_cookie"
local get_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["get"]["reqfile"]) local args_rules = require "rule_args"
local post_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["post"]["reqfile"]) local ip_white_rules = require "rule_ip_white"
local user_agent_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["user-agent"]["reqfile"]) local ip_black_rules = require "rule_ip_black"
local args_rules = C:read_file_table('args') local ipv6_black_rules = require "rule_ipv6_black"
local ip_white_rules = C:read_file('ip_white') local scan_black_rules = require "rule_scan_black"
local ip_black_rules = C:read_file('ip_black') local user_agent_rules = require "rule_user_agent"
local scan_black_rules = C:read_file('scan_black') local post_rules = require "rule_post"
local user_agent_rules = C:read_file('user_agent') local cookie_rules = require "rule_cookie"
local post_rules = C:read_file('post') local url_rules = require "rule_url"
local cookie_rules = C:read_file('cookie') local url_white_rules = require "rule_url_white"
local server_name = string.gsub(C:get_server_name(),'_','.') local server_name = string.gsub(C:get_sn(config_domains),'_','.')
local function initParams()
-- C:D("sss:"..C:get_server_name())
function initParams()
local data = {} local data = {}
data['server_name'] = server_name data['server_name'] = server_name
-- data['ip'] = C:get_client_ip() data['ip'] = C:get_real_ip(server_name)
-- data['ipn'] = C:arrip(data['ip']) data['ipn'] = C:arrip(data['ip'])
data['request_header'] = ngx.req.get_headers() data['request_header'] = ngx.req.get_headers()
data['uri'] = ngx.unescape_uri(ngx.var.uri) data['uri'] = tostring(ngx.unescape_uri(ngx.var.uri))
data['uri_request_args'] = ngx.req.get_uri_args() data['uri_request_args'] = ngx.req.get_uri_args()
data['method'] = ngx.req.get_method() data['method'] = ngx.req.get_method()
data['request_uri'] = ngx.var.request_uri data['request_uri'] = tostring(ngx.var.request_uri)
data['status_code'] = ngx.status
data['user_agent'] = data['request_header']['user-agent']
data['cookie'] = ngx.var.http_cookie data['cookie'] = ngx.var.http_cookie
data['time'] = ngx.time()
return data return data
end end
local params = initParams() local params = initParams()
C:setParams(params) C:setParams(params)
C:setDebug(true)
local server_name = params["server_name"] local cpu_percent = ngx.shared.waf_limit:get("cpu_usage")
params['ip'] = C:get_client_ip() if not cpu_percent then
params['ipn'] = C:arrip(params['ip']) cpu_percent = 0
C:D(server_name) end
function get_return_state(rstate,rmsg) local function get_return_state(rstate,rmsg)
result = {} result = {}
result['status'] = rstate result['status'] = rstate
result['msg'] = rmsg result['msg'] = rmsg
return result return result
end end
function get_waf_drop_ip() local function get_waf_drop_ip()
local data = ngx.shared.drop_ip:get_keys(0) local data = ngx.shared.waf_drop_ip:get_keys(0)
return data return data
end 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 type(data) ~= 'table' then return 1 end
if not data 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) for k,v in pairs(data)
do do
if strings ==v['ip'] then if strings == v['ip'] then
return 3 return 3
end end
end end
return 2 return 2
end end
function save_ip_on(data) local function remove_waf_drop_ip()
locak_file=read_file_body(cpath2 .. 'stop_ip.lock') ngx.header.content_type = "application/json"
if not locak_file then local ip = params['uri_request_args']['ip']
C:write_file(cpath2 .. 'stop_ip.lock','1')
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 end
name='stop_ip'
local extime=18000 local sign = "remove_waf_drop_ip"
data=json.encode(data) if C:is_working(sign) then
ngx.shared.btwaf:set(cpath2 .. name,data,extime) local data = get_return_state(-1, "fail")
if not ngx.shared.btwaf:get(cpath2 .. name .. '_lock') then ngx.say(json.encode(data))
ngx.shared.btwaf:set(cpath2 .. name .. '_lock',1,0.5) ngx.exit(200)
C:write_file(cpath2 .. name .. '.json',data) return true
end 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 end
function remove_waf_drop_ip() local function clean_waf_drop_ip()
if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end ngx.header.content_type = "application/json"
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
ret=ngx.shared.btwaf:get(cpath2 .. 'stop_ip') local sign = "clean_waf_drop_ip"
ip_data=json.decode(ret) if C:is_working(sign) then
result = is_chekc_table(ip_data,uri_request_args['ip']) local data = get_return_state(-1, "fail")
os.execute("sleep " .. 0.6) ngx.say(json.encode(data))
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip') ngx.exit(200)
ip_data2 = json.decode(ret2) return true
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)
end 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 end
function clean_waf_drop_ip() local function min_route()
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()
if ngx.var.remote_addr ~= '127.0.0.1' then return false end if ngx.var.remote_addr ~= '127.0.0.1' then return false end
local uri = params['uri']
if uri == '/get_waf_drop_ip' then 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 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 elseif uri == '/clean_waf_drop_ip' then
return_message(200,clean_waf_drop_ip()) clean_waf_drop_ip()
end end
end end
function waf_get_args() local function waf_get_args()
if not config['get']['open'] or not C:is_site_config('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['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:write_log('args','regular')
C:return_html(config['get']['status'], get_html) C:return_html(config['get']['status'], get_html)
return true return true
@@ -156,7 +172,7 @@ function waf_get_args()
end end
function waf_ip_white() local function waf_ip_white()
for _,rule in ipairs(ip_white_rules) for _,rule in ipairs(ip_white_rules)
do do
if C:compare_ip(rule) then if C:compare_ip(rule) then
@@ -166,7 +182,15 @@ function waf_ip_white()
return false return false
end end
function waf_ip_black() local function waf_url_white()
if C:ngx_match_list(url_white_rules, params['uri']) then
return true
end
return false
end
local function waf_ip_black()
-- ipv4 ip black
for _,rule in ipairs(ip_black_rules) for _,rule in ipairs(ip_black_rules)
do do
if C:compare_ip(rule) then if C:compare_ip(rule) then
@@ -174,117 +198,178 @@ function waf_ip_black()
return true return true
end end
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 return false
end end
function waf_user_agent() local function waf_user_agent()
-- user_agent 过滤 -- user_agent 过滤
if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end -- if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
if C:is_ngx_match_ua(user_agent_rules,params['request_header']['user-agent']) then
-- C:D("waf_user_agent;user_agent_rules:"..json.encode(user_agent_rules)..",ua:"..tostring(params['request_header']['user-agent']))
if C:ngx_match_list(user_agent_rules, params['request_header']['user-agent']) then
-- C:D("waf_user_agent........... true")
C:write_log('user_agent','regular') C:write_log('user_agent','regular')
C:return_html(config['user-agent']['status'],user_agent_html) C:return_html(config['user-agent']['status'], user_agent_html)
return true return true
end end
-- C:D("waf_user_agent........... false")
return false return false
end end
function waf_drop() local function waf_drop_ip()
local count , _ = ngx.shared.drop_ip:get(ip) local ip = params['ip']
local count = ngx.shared.waf_drop_ip:get(ip)
if not count then return false end 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']) ngx.exit(config['cc']['status'])
return true return true
end end
-- C:D("waf_drop_ip........... false")
return false return false
end end
function waf_cc() local function waf_cc()
local ip = params['ip']
local ip_lock = ngx.shared.drop_ip:get(ip)
if ip_lock then
if ip_lock > 0 then
ngx.exit(config['cc']['status'])
return true
end
end
if not config['cc']['open'] or not C:is_site_config('cc') then return false end if not config['cc']['open'] or not C:is_site_config('cc') then return false end
local ip = params['ip']
-- 多次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 request_uri = params['request_uri']
local endtime = config['cc']['endtime']
local token = ngx.md5(ip .. '_' .. 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 limit = config['cc']['limit'] local endtime = config['cc']['endtime']
local waf_limit = config['cc']['limit']
local cycle = config['cc']['cycle'] local cycle = config['cc']['cycle']
if count then if count then
if count > limit then if count > waf_limit then
local safe_count, _ = ngx.shared.drop_sum:get(ip) local safe_count, _ = ngx.shared.waf_drop_sum:get(ip)
if not safe_count then 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 safe_count = 1
else else
ngx.shared.drop_sum:incr(ip,1) ngx.shared.waf_drop_sum:incr(ip, 1)
end end
local lock_time = (endtime * safe_count) local lock_time = (endtime * safe_count)
if lock_time > 86400 then lock_time = 86400 end if lock_time > 86400 then lock_time = 86400 end
-- lock_time = 10 ngx.shared.waf_drop_ip:set(ip, 1, lock_time)
ngx.shared.drop_ip:set(ip,1,lock_time) local reason = cycle..'秒内累计超过'..waf_limit..'次请求,封锁' .. lock_time .. '秒'
C:write_log('cc', reason)
C:write_log('cc',cycle..'秒内累计超过'..limit..'次请求,封锁' .. lock_time .. '秒') C:log(params, 'cc',reason)
C:write_drop_ip('cc',lock_time)
ngx.exit(config['cc']['status']) ngx.exit(config['cc']['status'])
return true return true
else else
ngx.shared.limit:incr(token,1) ngx.shared.waf_limit:incr(token, 1)
end end
else else
ngx.shared.drop_sum:set(ip,1,86400) ngx.shared.waf_drop_sum:set(ip, 1, 86400)
ngx.shared.limit:set(token, 1, cycle) ngx.shared.waf_limit:set(token, 1, cycle)
end end
return false return false
end end
--强制验证是否使用正常浏览器访问网站 -- 是否符合开强制验证条件
function waf_cc_increase() local function is_open_waf_cc_increase()
if not config['cc']['open'] or not site_cc then return false end if config['safe_verify']['open'] then
if not site_config[server_name] then return false end return true
if not site_config[server_name]['cc']['increase'] then return false end
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
end end
if security_verification() then return false end
send_check_heml(cache_token) -- C:D("waf config:"..json.encode(config))
if cpu_percent >= config['safe_verify']['cpu'] then
return true
end
if site_config[server_name] and site_config[server_name]['safe_verify']['open'] then
if cpu_percent >= site_config[server_name]['safe_verify']['cpu'] then
return true
end
end
return false
end end
function waf_url() --强制验证是否使用正常浏览器访问网站
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.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
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
local function waf_url()
if not config['get']['open'] or not C:is_site_config('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(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:write_log('url','regular')
C:return_html(config['get']['status'],get_html) C:return_html(config['get']['status'], get_html)
return true return true
end end
return false return false
end 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 not config['scan']['open'] or not C:is_site_config('scan') then return false end
if not params["cookie"] then if not params["cookie"] then
@@ -312,18 +397,17 @@ function waf_scan_black()
return false return false
end 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 not config['post']['open'] or not C:is_site_config('post') then return false end
if params['method'] ~= "POST" then return false end if params['method'] ~= "POST" then return false end
content_length = tonumber(params["request_header"]['content-length']) local content_length = tonumber(params["request_header"]['content-length'])
max_len = 640 * 1020000 local max_len = 640 * 1020000
if content_length > max_len then return false end if content_length > max_len then return false end
if C:get_boundary() then return false end if C:get_boundary() then return false end
ngx.req.read_body() ngx.req.read_body()
request_args = ngx.req.get_post_args()
if not request_args then local request_args = params['uri_request_args']
return false if not request_args then return false end
end
for key, val in pairs(request_args) do for key, val in pairs(request_args) do
if type(val) == "table" then if type(val) == "table" then
@@ -334,124 +418,54 @@ function waf_post()
else else
data = val data = val
end end
end end
if C:is_ngx_match_post(post_rules,data) then -- C:D("post:"..json.encode(data))
if C:ngx_match_list(post_rules, data) then
C:write_log('post','regular') C:write_log('post','regular')
C:return_html(config['post']['status'],post_html) C:return_html(config['post']['status'], post_html)
return true return true
end end
return false return false
end 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(post_rules , data_len) 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 params['method'] ~= "GET" then return false end
if not config['get']['open'] or not C:is_site_config('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:write_log('args','regular')
C:return_html(config['get']['status'],get_html) C:return_html(config['get']['status'], get_html)
return true return true
end end
return false return false
end 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 not config['post']['open'] or not C:is_site_config('post') then return false end
if params['method'] ~= "POST" then return false end if params['method'] ~= "POST" then return false end
if C:is_ngx_match_post(post_rules,params["request_header"]['X-forwarded-For']) then if not params["request_header"]['X-forwarded-For'] then return false end
if C:ngx_match_list(post_rules, params["request_header"]['X-forwarded-For']) then
C:write_log('post','regular') C:write_log('post','regular')
C:return_html(config['post']['status'],post_html) C:return_html(config['post']['status'], post_html)
return true return true
end end
return false return false
end end
local function url_ext()
-- 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 C:ngx_match_string(params['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()
if site_config[server_name] == nil then return false end if site_config[server_name] == nil then return false end
for _,rule in ipairs(site_config[server_name]['disable_ext']) for _,rule in ipairs(site_config[server_name]['disable_ext'])
do do
if C:ngx_match_string("\\."..rule.."$", params['uri'],'url_ext') then if C:ngx_match_string("\\."..rule.."$", params['uri'],'url_ext') then
C:write_log('url_ext','regular') 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) C:return_html(config['other']['status'], other_html)
return true return true
end end
@@ -459,103 +473,39 @@ function url_ext()
return false return false
end end
function url_rule_ex() local function disable_upload_ext(ext)
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)
if not ext then return false end if not ext then return false end
ext = string.lower(ext) local ext = string.lower(ext)
if is_key(site_config[server_name]['disable_upload_ext'],ext) then if C:is_key(site_config[server_name]['disable_upload_ext'], ext) then
C:write_log('upload_ext','上传扩展名黑名单') C:write_log('upload_ext', '上传扩展名黑名单')
C:return_html(config['other']['status'],other_html) C:return_html(config['other']['status'],other_html)
return true return true
end end
return false
end end
function data_in_php(data) local function post_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()
if params["method"] ~= "POST" then return false end 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 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 if content_length > max_len then return false end
local boundary = C:get_boundary() local boundary = C:get_boundary()
-- C:D("boundary:".. tostring( boundary) )
if boundary then if boundary then
ngx.req.read_body() ngx.req.read_body()
local data = ngx.req.get_body_data() local data = ngx.req.get_body_data()
if not data then return false end if not data then return false end
local tmp = ngx.re.match(data,[[filename=\"(.+)\.(.*)\"]]) local tmp = ngx.re.match(data,[[filename=\"(.+)\.(.*)\"]])
if not tmp then return false end if not tmp or not tmp[2] then return false end
if not tmp[2] then return false end -- C:D("upload_ext:".. tostring(tmp[2]) )
local tmp2=ngx.re.match(ngx.req.get_body_data(),[[Content-Type:[^\+]{45}]])
--return return_message(200,tmp2[0])
disable_upload_ext(tmp[2]) disable_upload_ext(tmp[2])
if tmp2 == nil then return false end
data_in_php(tmp2[0])
end end
return false return false
end 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 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 not params["request_header"]['cookie'] then return false end
if type(params["request_header"]['cookie']) ~= "string" then return false end if type(params["request_header"]['cookie']) ~= "string" then return false end
@@ -575,18 +525,23 @@ function waf()
-- white ip -- white ip
if waf_ip_white() then return true end if waf_ip_white() then return true end
-- url white
if waf_url_white() then return true end
-- black ip -- black ip
if waf_ip_black() then return true end if waf_ip_black() then return true end
-- 封禁ip返回
-- cc setting if waf_drop_ip() then return true end
if waf_drop() then return true end
if waf_cc() then return true end
-- ua check -- ua check
if waf_user_agent() then return true end if waf_user_agent() then return true end
if waf_url() then return true end if waf_url() then return true end
-- cc setting
if waf_cc_increase() then return true end
if waf_cc() then return true end
-- cookie检查 -- cookie检查
if waf_cookie() then return true end if waf_cookie() then return true end
@@ -597,16 +552,12 @@ function waf()
if waf_scan_black() then return true end if waf_scan_black() then return true end
if waf_post() then return true end if waf_post() then return true end
if post_data_chekc() then return true end
if site_config[server_name]['open'] then if site_config[server_name] and site_config[server_name]['open'] then
if X_Forwarded() then return true end if X_Forwarded() then return true end
if post_X_Forwarded() then return true end if post_X_Forwarded() then return true end
-- url_path()
if url_ext() then return true end if url_ext() then return true end
-- url_rule_ex() if post_data() then return true end
-- url_tell()
-- post_data()
end 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 @@
[[[127, 0, 0, 2], [127, 0, 0, 255]]] [[[127, 0, 0, 1], [127, 0, 0, 255]]]
+1
View File
@@ -0,0 +1 @@
[[1,"^/(phpmyadmin)","MySQL[phpMyAdmin]", 0]]
+1 -1
View File
@@ -1 +1 @@
{"rules":{"url_ext":0,"user_agent":0,"scan":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\.
-1
View File
@@ -1 +0,0 @@
^/phpmyadmin_
+3
View File
@@ -64,6 +64,9 @@ Install_openresty()
--with-http_slice_module \ --with-http_slice_module \
--with-http_stub_status_module \ --with-http_stub_status_module \
--with-http_realip_module --with-http_realip_module
# --without-luajit-gc64
# --with-debug
# 用于调式
make -j${cpuCore} && make install && make clean 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 = /run/php/php{$PHP_VERSION}-fpm.sock
listen.owner = {$PHP_USER} listen.owner = {$PHP_USER}
listen.group = {$PHP_GROUP} listen.group = {$PHP_GROUP}
listen.backlog = 4096
pm = dynamic pm = dynamic
pm.max_children = 50 pm.max_children = 50
pm.start_servers = 5 pm.start_servers = 5
+2 -2
View File
@@ -537,7 +537,7 @@ def setSessionConf(version):
passwd = args['passwd'] passwd = args['passwd']
save_handler = args['save_handler'] save_handler = args['save_handler']
if save_handler != "file": if save_handler != "files":
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})" 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): if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址') return mw.returnJson(False, '请输入正确的IP地址')
@@ -605,7 +605,7 @@ def setSessionConf(version):
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"', phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini) '\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
if save_handler == "file": if save_handler == "files":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n' rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n' val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini): if re.search(rep, phpini):
+3 -3
View File
@@ -380,7 +380,7 @@ function getSessionConfig(version){
} }
var rdata = rdata.data; var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" + var cacheList = "<option value='files' " + (rdata.save_handler == "files" ? 'selected' : '') + ">files</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" + "<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" + "<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>"; "<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
@@ -405,7 +405,7 @@ function getSessionConfig(version){
$(".soft-man-con").html(con); $(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){ if (rdata.save_handler == 'files'){
$('input[name="ip"]').attr('disabled','disabled'); $('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled'); $('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空'); $('input[name="passwd"]').attr('placeholder','如果没有密码留空');
@@ -436,7 +436,7 @@ function getSessionConfig(version){
$('input[name="port"]').removeAttr('disabled'); $('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled'); $('input[name="passwd"]').removeAttr('disabled');
break; break;
case 'file': case 'files':
$('input[name="ip"]').val("").attr('disabled','disabled'); $('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled'); $('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled'); $('input[name="passwd"]').val("").attr('disabled','disabled');
+2
View File
@@ -5,6 +5,8 @@ group = {$PHP_GROUP}
listen = /var/opt/remi/php{$PHP_VERSION}/run/php-fpm/www.sock listen = /var/opt/remi/php{$PHP_VERSION}/run/php-fpm/www.sock
listen.owner = {$PHP_USER} listen.owner = {$PHP_USER}
listen.group = {$PHP_GROUP} listen.group = {$PHP_GROUP}
listen.backlog = 4096
pm = dynamic pm = dynamic
pm.max_children = 50 pm.max_children = 50
pm.start_servers = 5 pm.start_servers = 5
+2 -2
View File
@@ -539,7 +539,7 @@ def setSessionConf(version):
passwd = args['passwd'] passwd = args['passwd']
save_handler = args['save_handler'] save_handler = args['save_handler']
if save_handler != "file": if save_handler != "files":
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})" 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): if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址') return mw.returnJson(False, '请输入正确的IP地址')
@@ -607,7 +607,7 @@ def setSessionConf(version):
phpini = re.sub('\n;session.save_path = "/tmp"', phpini = re.sub('\n;session.save_path = "/tmp"',
'\n;session.save_path = "/tmp"' + val, phpini) '\n;session.save_path = "/tmp"' + val, phpini)
if save_handler == "file": if save_handler == "files":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n' rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n' val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini): if re.search(rep, phpini):
+3 -3
View File
@@ -349,7 +349,7 @@ function getSessionConfig(version){
} }
var rdata = rdata.data; var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" + var cacheList = "<option value='files' " + (rdata.save_handler == "files" ? 'selected' : '') + ">files</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" + "<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" + "<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>"; "<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
@@ -374,7 +374,7 @@ function getSessionConfig(version){
$(".soft-man-con").html(con); $(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){ if (rdata.save_handler == 'files'){
$('input[name="ip"]').attr('disabled','disabled'); $('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled'); $('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空'); $('input[name="passwd"]').attr('placeholder','如果没有密码留空');
@@ -405,7 +405,7 @@ function getSessionConfig(version){
$('input[name="port"]').removeAttr('disabled'); $('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled'); $('input[name="passwd"]').removeAttr('disabled');
break; break;
case 'file': case 'files':
$('input[name="ip"]').val("").attr('disabled','disabled'); $('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled'); $('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled'); $('input[name="passwd"]').val("").attr('disabled','disabled');
+3
View File
@@ -1,9 +1,12 @@
[www] [www]
user = {$PHP_USER} user = {$PHP_USER}
group = {$PHP_GROUP} group = {$PHP_GROUP}
listen = /tmp/php-cgi-{$PHP_VERSION}.sock listen = /tmp/php-cgi-{$PHP_VERSION}.sock
listen.owner = {$PHP_USER} listen.owner = {$PHP_USER}
listen.group = {$PHP_GROUP} listen.group = {$PHP_GROUP}
listen.backlog = 4096
pm = dynamic pm = dynamic
pm.max_children = 50 pm.max_children = 50
pm.start_servers = 5 pm.start_servers = 5
+2 -2
View File
@@ -679,7 +679,7 @@ def setSessionConf(version):
passwd = args['passwd'] passwd = args['passwd']
save_handler = args['save_handler'] save_handler = args['save_handler']
if save_handler != "file": if save_handler != "files":
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})" 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): if not re.search(iprep, ip):
return mw.returnJson(False, '请输入正确的IP地址') return mw.returnJson(False, '请输入正确的IP地址')
@@ -743,7 +743,7 @@ def setSessionConf(version):
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"', phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
'\n;session.save_path = "' + session_tmp + '"' + val, phpini) '\n;session.save_path = "' + session_tmp + '"' + val, phpini)
if save_handler == "file": if save_handler == "files":
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n' rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
val = r'\nsession.save_path = "' + session_tmp + '"\n' val = r'\nsession.save_path = "' + session_tmp + '"\n'
if re.search(rep, phpini): if re.search(rep, phpini):
+3 -3
View File
@@ -339,7 +339,7 @@ function getSessionConfig(version){
} }
var rdata = rdata.data; var rdata = rdata.data;
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" + var cacheList = "<option value='files' " + (rdata.save_handler == "files" ? 'selected' : '') + ">files</option>" +
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" + "<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" + "<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>"; "<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
@@ -364,7 +364,7 @@ function getSessionConfig(version){
$(".soft-man-con").html(con); $(".soft-man-con").html(con);
if (rdata.save_handler == 'file'){ if (rdata.save_handler == 'files'){
$('input[name="ip"]').attr('disabled','disabled'); $('input[name="ip"]').attr('disabled','disabled');
$('input[name="port"]').attr('disabled','disabled'); $('input[name="port"]').attr('disabled','disabled');
$('input[name="passwd"]').attr('placeholder','如果没有密码留空'); $('input[name="passwd"]').attr('placeholder','如果没有密码留空');
@@ -395,7 +395,7 @@ function getSessionConfig(version){
$('input[name="port"]').removeAttr('disabled'); $('input[name="port"]').removeAttr('disabled');
$('input[name="passwd"]').removeAttr('disabled'); $('input[name="passwd"]').removeAttr('disabled');
break; break;
case 'file': case 'files':
$('input[name="ip"]').val("").attr('disabled','disabled'); $('input[name="ip"]').val("").attr('disabled','disabled');
$('input[name="port"]').val("").attr('disabled','disabled'); $('input[name="port"]').val("").attr('disabled','disabled');
$('input[name="passwd"]').val("").attr('disabled','disabled'); $('input[name="passwd"]').val("").attr('disabled','disabled');
+3 -2
View File
@@ -17,6 +17,7 @@
</div> </div>
<script type="text/javascript"> <script type="text/javascript">
$.getScript( "/plugins/file?name=phpmyadmin&f=js/phpmyadmin.js"); $.getScript( "/plugins/file?name=phpmyadmin&f=js/phpmyadmin.js", function(){
pluginService('phpmyadmin'); pluginService('phpmyadmin');
});
</script> </script>
+6
View File
@@ -124,6 +124,10 @@ def contentReplace(content):
content = content.replace('{$CHOOSE_DB}', 'MariaDB') content = content.replace('{$CHOOSE_DB}', 'MariaDB')
content = content.replace('{$CHOOSE_DB_DIR}', 'mariadb') content = content.replace('{$CHOOSE_DB_DIR}', 'mariadb')
port = cfg["port"]
rep = 'listen\s*(.*);'
content = re.sub(rep, "listen " + port + ';', content)
return content return content
@@ -284,6 +288,8 @@ def setPmaPort():
rep = 'listen\s*(.*);' rep = 'listen\s*(.*);'
content = re.sub(rep, "listen " + port + ';', content) content = re.sub(rep, "listen " + port + ';', content)
mw.writeFile(file, content) mw.writeFile(file, content)
setCfg("port", port)
mw.restartWeb() mw.restartWeb()
return mw.returnJson(True, '修改成功!') return mw.returnJson(True, '修改成功!')
+11 -1
View File
@@ -10,10 +10,20 @@ serverPath=$(dirname "$rootPath")
install_tmp=${rootPath}/tmp/mw_install.pl install_tmp=${rootPath}/tmp/mw_install.pl
if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate
fi
if [ "$sys_os" == "Darwin" ];then
BAK='_bak'
else
BAK=''
fi
sysName=`uname` sysName=`uname`
echo "use system: ${sysName}" echo "use system: ${sysName}"
if [ ${sysName} == "Darwin" ]; then if [ "${sysName}" == "Darwin" ]; then
OSNAME='macos' OSNAME='macos'
elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then elif grep -Eqi "CentOS" /etc/issue || grep -Eq "CentOS" /etc/*-release; then
OSNAME='centos' OSNAME='centos'
+4 -1
View File
@@ -25,5 +25,8 @@ AutoRename no
AnonymousCantUpload no AnonymousCantUpload no
MaxDiskUsage 99 MaxDiskUsage 99
CustomerProof yes CustomerProof yes
PIDFile /var/run/pure-ftpd.pid PassivePortRange 48000 50000
PIDFile {$SERVER_PATH}/pureftp/etc/pure-ftpd.pid
PureDB {$SERVER_PATH}/pureftp/etc/pureftpd.pdb PureDB {$SERVER_PATH}/pureftp/etc/pureftpd.pdb
VerboseLog yes
+3 -2
View File
@@ -110,8 +110,9 @@ def initDreplace():
pureFtpdConfigBak = getServerDir() + "/etc/pure-ftpd.bak.conf" pureFtpdConfigBak = getServerDir() + "/etc/pure-ftpd.bak.conf"
pureFtpdConfigTpl = getPluginDir() + "/conf/pure-ftpd.conf" pureFtpdConfigTpl = getPluginDir() + "/conf/pure-ftpd.conf"
if not os.path.exists(pureFtpdConfigBak): if not os.path.exists(pureFtpdConfigBak) or not os.path.exists(pureFtpdConfig):
shutil.copyfile(pureFtpdConfig, pureFtpdConfigBak) if os.path.exists(pureFtpdConfig):
shutil.copyfile(pureFtpdConfig, pureFtpdConfigBak)
content = mw.readFile(pureFtpdConfigTpl) content = mw.readFile(pureFtpdConfigTpl)
content = contentReplace(content) content = contentReplace(content)
mw.writeFile(pureFtpdConfig, content) mw.writeFile(pureFtpdConfig, content)
+1 -1
View File
@@ -10,7 +10,7 @@ my ($conffile, @flg) = @ARGV;
my $PUREFTPD; my $PUREFTPD;
-x && ($PUREFTPD=$_, last) for qw( -x && ($PUREFTPD=$_, last) for qw(
{$SERVER_PATH}/pureftp/sbin/pure-ftpd {$SERVER_PATH}/pureftp/sbin/pure-ftpd
/www/server/pure-ftpd/sbin/pure-ftpd /www/server/pureftp/sbin/pure-ftpd
/www/server/pureftpd/sbin/pure-ftpd /www/server/pureftpd/sbin/pure-ftpd
/www/server/sbin/pure-ftpd /www/server/sbin/pure-ftpd
/usr/sbin/pure-ftpd /usr/sbin/pure-ftpd
+1 -1
View File
@@ -17,7 +17,7 @@
# Pure-FTPd Settings # Pure-FTPd Settings
PURE_PERL="{$SERVER_PATH}/pureftp/sbin/pure-config.pl" PURE_PERL="{$SERVER_PATH}/pureftp/sbin/pure-config.pl"
PURE_CONF="{$SERVER_PATH}/pureftp/etc/pure-ftpd.conf" PURE_CONF="{$SERVER_PATH}/pureftp/etc/pure-ftpd.conf"
PURE_PID="/var/run/pure-ftpd.pid" PURE_PID="{$SERVER_PATH}/pureftp/etc/pure-ftpd.pid"
RETVAL=0 RETVAL=0
prog="Pure-FTPd" prog="Pure-FTPd"
+22 -4
View File
@@ -53,8 +53,8 @@ Install_pureftp()
# curl -sSLo pure-ftpd-1.0.49.tar.gz https://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.49.tar.gz # curl -sSLo pure-ftpd-1.0.49.tar.gz https://download.pureftpd.org/pub/pure-ftpd/releases/pure-ftpd-1.0.49.tar.gz
if [ ! -f $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz ];then if [ ! -f $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz ];then
# wget --no-check-certificate -O $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD wget --no-check-certificate -O $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD # curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
fi fi
#检测文件是否损坏. #检测文件是否损坏.
@@ -66,7 +66,8 @@ Install_pureftp()
else else
# 重新下载 # 重新下载
rm -rf $serverPath/source/pureftp/pure-ftpd-${VER} rm -rf $serverPath/source/pureftp/pure-ftpd-${VER}
curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD wget --no-check-certificate -O $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
# curl -sSLo $serverPath/source/pureftp/pure-ftpd-${VER}.tar.gz $DOWNLOAD
fi fi
fi fi
@@ -75,7 +76,24 @@ Install_pureftp()
fi fi
cd $serverPath/source/pureftp/pure-ftpd-${VER} && ./configure --prefix=${serverPath}/pureftp \ cd $serverPath/source/pureftp/pure-ftpd-${VER} && ./configure --prefix=${serverPath}/pureftp \
   --with-everything && make && make install && make clean    CFLAGS=-O2 \
--with-puredb \
--with-quotas \
--with-cookie \
--with-virtualhosts \
--with-diraliases \
--with-sysquotas \
--with-ratios \
--with-altlog \
--with-paranoidmsg \
--with-shadow \
--with-welcomemsg \
--with-throttling \
--with-uploadscript \
--with-language=english \
--with-rfc2640 \
--with-ftpwho \
--with-tls && make && make install && make clean
if [ -d ${serverPath}/pureftp ];then if [ -d ${serverPath}/pureftp ];then
echo "${1}" > ${serverPath}/pureftp/version.pl echo "${1}" > ${serverPath}/pureftp/version.pl
+1 -11
View File
@@ -1,18 +1,8 @@
function str2Obj(str){
var data = {};
kv = str.split('&');
for(i in kv){
v = kv[i].split('=');
data[v[0]] = v[1];
}
return data;
}
function ftpPost(method,args,callback){ function ftpPost(method,args,callback){
var _args = null; var _args = null;
if (typeof(args) == 'string'){ if (typeof(args) == 'string'){
_args = JSON.stringify(str2Obj(args)); _args = JSON.stringify(toArrayObject(args));
} else { } else {
_args = JSON.stringify(args); _args = JSON.stringify(args);
} }
+31 -14
View File
@@ -1,18 +1,35 @@
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.ipv4.icmp_echo_ignore_all=0
net.ipv4.tcp_fin_timeout = 6 net.ipv4.ip_forward = 0
net.ipv4.tcp_keepalive_time = 30 net.ipv4.conf.default.rp_filter = 1
net.ipv4.tcp_max_tw_buckets = 8000 net.ipv4.conf.default.accept_source_route = 0
net.ipv4.tcp_tw_reuse = 1 kernel.sysrq = 0
net.ipv4.tcp_tw_recycle = 1 kernel.core_uses_pid = 1
net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 30000 kernel.msgmnb = 65536
net.ipv4.tcp_syn_retries = 2 kernel.msgmax = 65536
net.ipv4.tcp_synack_retries = 2 kernel.shmmax = 68719476736
net.ipv4.ip_local_port_range = 1025 61000 kernel.shmall = 4294967296
net.ipv4.tcp_keepalive_intvl = 3 net.ipv4.tcp_max_tw_buckets = 6000
net.ipv4.tcp_keepalive_probes = 2 net.ipv4.tcp_sack = 1
net.ipv4.tcp_window_scaling = 1
net.ipv4.tcp_rmem = 4096 87380 4194304
net.ipv4.tcp_wmem = 4096 16384 4194304
net.core.wmem_default = 8388608
net.core.rmem_default = 8388608
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.netdev_max_backlog = 262144
net.core.somaxconn = 262144
net.ipv4.tcp_max_orphans = 3276800
net.ipv4.tcp_max_syn_backlog = 262144
net.ipv4.tcp_timestamps = 0
net.ipv4.tcp_synack_retries = 1
net.ipv4.tcp_syn_retries = 1
net.ipv4.tcp_tw_recycle = 1
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_mem = 94500000 915000000 927000000
net.ipv4.tcp_fin_timeout = 1
net.ipv4.tcp_keepalive_time = 30
net.ipv4.ip_local_port_range = 1024 65000
vm.overcommit_memory=1 vm.overcommit_memory=1
+1 -1
View File
@@ -1,2 +1,2 @@
lua_shared_dict mw_total 50m; lua_shared_dict mw_total 100m;
include {$SERVER_APP}/lua/webstats_log.lua; include {$SERVER_APP}/lua/webstats_log.lua;
+35 -15
View File
@@ -77,11 +77,11 @@ def status():
return 'start' return 'start'
def loadLuaLogFile(): def loadLuaFile(name):
lua_dir = getServerDir() + "/lua" lua_dir = getServerDir() + "/lua"
lua_dst = lua_dir + "/webstats_log.lua" lua_dst = lua_dir + "/" + name
lua_tpl = getPluginDir() + '/lua/webstats_log.lua' lua_tpl = getPluginDir() + '/lua/' + name
content = mw.readFile(lua_tpl) content = mw.readFile(lua_tpl)
content = content.replace('{$SERVER_APP}', getServerDir()) content = content.replace('{$SERVER_APP}', getServerDir())
content = content.replace('{$ROOT_PATH}', mw.getServerDir()) content = content.replace('{$ROOT_PATH}', mw.getServerDir())
@@ -98,7 +98,7 @@ def loadConfigFile():
dst_conf_json = getServerDir() + "/lua/config.json" dst_conf_json = getServerDir() + "/lua/config.json"
mw.writeFile(dst_conf_json, json.dumps(content)) mw.writeFile(dst_conf_json, json.dumps(content))
dst_conf_lua = getServerDir() + "/lua/config.lua" dst_conf_lua = getServerDir() + "/lua/webstats_config.lua"
listToLuaFile(dst_conf_lua, content) listToLuaFile(dst_conf_lua, content)
@@ -125,9 +125,16 @@ def loadLuaSiteFile():
ddata["default"] = "unset" ddata["default"] = "unset"
else: else:
ddata["default"] = dlist[0] ddata["default"] = dlist[0]
mw.writeFile(default_json, json.dumps(ddata)) mw.writeFile(default_json, json.dumps(ddata))
lua_site = lua_dir + "/sites.lua" lua_site = lua_dir + "/webstats_sites.lua"
tmp = {
"name": "unset",
"domains": [],
}
content.append(tmp)
listToLuaFile(lua_site, content) listToLuaFile(lua_site, content)
@@ -205,7 +212,14 @@ def initDreplace():
if not os.path.exists(log_path): if not os.path.exists(log_path):
mw.execShell('mkdir -p ' + log_path) mw.execShell('mkdir -p ' + log_path)
loadLuaLogFile() file_list = [
'webstats_common.lua',
'webstats_log.lua',
]
for fl in file_list:
loadLuaFile(fl)
loadConfigFile() loadConfigFile()
loadLuaSiteFile() loadLuaSiteFile()
loadDebugLogFile() loadDebugLogFile()
@@ -222,28 +236,35 @@ def start():
if not mw.isAppleSystem(): if not mw.isAppleSystem():
mw.execShell("chown -R www:www " + getServerDir()) mw.execShell("chown -R www:www " + getServerDir())
mw.restartWeb() mw.opWeb("reload")
return 'ok' return 'ok'
def stop(): def stop():
path = luaConf() path = luaConf()
os.remove(path) if os.path.exists(path):
mw.restartWeb() os.remove(path)
import tool_task
tool_task.removeBgTask()
mw.opWeb("restart")
return 'ok' return 'ok'
def restart(): def restart():
initDreplace() initDreplace()
mw.opWeb("reload")
return 'ok' return 'ok'
def reload(): def reload():
initDreplace() initDreplace()
loadLuaLogFile()
loadDebugLogFile() loadDebugLogFile()
mw.restartWeb()
mw.opWeb("reload")
return 'ok' return 'ok'
@@ -294,7 +315,7 @@ def setGlobalConf():
content['global']['exclude_url'] = exclude_url_val content['global']['exclude_url'] = exclude_url_val
mw.writeFile(conf, json.dumps(content)) mw.writeFile(conf, json.dumps(content))
conf_lua = getServerDir() + "/lua/config.lua" conf_lua = getServerDir() + "/lua/webstats_config.lua"
listToLuaFile(conf_lua, content) listToLuaFile(conf_lua, content)
mw.restartWeb() mw.restartWeb()
return mw.returnJson(True, '设置成功') return mw.returnJson(True, '设置成功')
@@ -387,7 +408,7 @@ def setSiteConf():
content[domain] = site_conf content[domain] = site_conf
mw.writeFile(conf, json.dumps(content)) mw.writeFile(conf, json.dumps(content))
conf_lua = getServerDir() + "/lua/config.lua" conf_lua = getServerDir() + "/lua/webstats_config.lua"
listToLuaFile(conf_lua, content) listToLuaFile(conf_lua, content)
mw.restartWeb() mw.restartWeb()
return mw.returnJson(True, '设置成功') return mw.returnJson(True, '设置成功')
@@ -622,7 +643,7 @@ def getLogsList():
limit = str(page_size) + ' offset ' + str(page_size * (page - 1)) limit = str(page_size) + ' offset ' + str(page_size * (page - 1))
conn = pSqliteDb('web_logs', domain) conn = pSqliteDb('web_logs', domain)
field = 'time,ip,domain,server_name,method,protocol,status_code,request_headers,ip_list,client_port,body_length,user_agent,referer,request_time,uri,body_length' field = 'time,ip,domain,server_name,method,is_spider,protocol,status_code,request_headers,ip_list,client_port,body_length,user_agent,referer,request_time,uri,body_length'
condition = '' condition = ''
conn = conn.field(field) conn = conn.field(field)
conn = conn.where("1=1", ()) conn = conn.where("1=1", ())
@@ -1101,7 +1122,6 @@ def getUriStatList():
conn = conn.where("day>? and flow>?", (0, 0,)) conn = conn.where("day>? and flow>?", (0, 0,))
clist = conn.order("flow desc").limit("50").inquiry(origin_field) clist = conn.order("flow desc").limit("50").inquiry(origin_field)
# print(clist)
total_req = 0 total_req = 0
total_flow = 0 total_flow = 0
+2 -2
View File
@@ -1,10 +1,10 @@
{ {
"sort": 7, "sort": 7,
"ps": "[DEV]网站统计报表[此插件-需要小白鼠反馈问题,慎用!]", "ps": "网站统计报表",
"name": "webstats", "name": "webstats",
"title": "网站统计", "title": "网站统计",
"shell": "install.sh", "shell": "install.sh",
"versions":["0.2.0"], "versions":["0.2.2"],
"tip": "soft", "tip": "soft",
"install_pre_inspection":true, "install_pre_inspection":true,
"checks": "server/webstats", "checks": "server/webstats",
+18 -14
View File
@@ -24,12 +24,14 @@ if [ -f ${rootPath}/bin/activate ];then
source ${rootPath}/bin/activate source ${rootPath}/bin/activate
fi fi
get_latest_release() {
curl -sL "https://api.github.com/repos/$1/releases/latest" | grep '"tag_name":' | cut -d'"' -f4
}
Install_App() Install_App()
{ {
echo '正在安装脚本文件...' > $install_tmp echo '正在安装脚本文件...' > $install_tmp
mkdir -p $serverPath/source/webstats mkdir -p $serverPath/source/webstats
mkdir -p $serverPath/webstats mkdir -p $serverPath/webstats
# 下载源码安装包 # 下载源码安装包
@@ -88,29 +90,31 @@ Install_App()
# https://github.com/P3TERX/GeoLite.mmdb # https://github.com/P3TERX/GeoLite.mmdb
pip install geoip2 pip install geoip2
if [ ! -f $serverPath/webstats/GeoLite2-City.mmdb ];then # if [ ! -f $serverPath/webstats/GeoLite2-City.mmdb ];then
# pip install geoip2 # wget --no-check-certificate -O $serverPath/webstats/GeoLite2-City.mmdb https://github.com/P3TERX/GeoLite.mmdb/releases/download/2022.10.16/GeoLite2-City.mmdb
wget --no-check-certificate -O $serverPath/webstats/GeoLite2-City.mmdb https://git.io/GeoLite2-City.mmdb # fi
# 缓存数据
GEO_VERSION=$(get_latest_release "P3TERX/GeoLite.mmdb")
if [ ! -f $serverPath/source/webstats/GeoLite2-City.mmdb ];then
wget --no-check-certificate -O $serverPath/source/webstats/GeoLite2-City.mmdb https://github.com/P3TERX/GeoLite.mmdb/releases/download/${GEO_VERSION}/GeoLite2-City.mmdb
fi fi
# GeoLite2-Country.mmdb if [ -f $serverPath/source/webstats/GeoLite2-City.mmdb ];then
cp -rf $serverPath/source/webstats/GeoLite2-City.mmdb $serverPath/webstats/GeoLite2-City.mmdb
fi
echo "${VERSION}" > $serverPath/webstats/version.pl echo "${VERSION}" > $serverPath/webstats/version.pl
echo '安装完成' > $install_tmp echo '安装完成' > $install_tmp
if [ "$sys_os" != "Darwin" ];then cd $rootPath && python3 ${rootPath}/plugins/webstats/index.py start
cd $rootPath && python3 ${rootPath}/plugins/webstats/index.py start
fi
} }
Uninstall_App() Uninstall_App()
{ {
if [ "$sys_os" != "Darwin" ];then cd $rootPath && python3 ${rootPath}/plugins/webstats/index.py stop
cd $rootPath && python3 ${rootPath}/plugins/webstats/index.py stop
fi
rm -rf $serverPath/webstats rm -rf $serverPath/webstats
echo "Uninstall_redis" > $install_tmp echo "卸载完成" > $install_tmp
} }
action=$1 action=$1
+1 -1
View File
@@ -247,7 +247,7 @@ wsPost('get_global_conf', '' ,{}, function(rdata){
$('#setAll').click(function(){ $('#setAll').click(function(){
var args = "name=webstats&func=reload"; var args = "name=webstats&func=reload";
layer.confirm('您真的要同步所有站点吗?', {icon:3,closeBtn: 2}, function() { layer.confirm('您真的要同步所有站点吗?', {icon:3,closeBtn: 1}, function() {
var e = layer.msg('正在同步,请稍候...', {icon: 16,time: 0}); var e = layer.msg('正在同步,请稍候...', {icon: 16,time: 0});
$.post("/plugins/run", args, function(g) { $.post("/plugins/run", args, function(g) {
layer.close(e); layer.close(e);
+32 -13
View File
@@ -2032,7 +2032,7 @@ function wsTableErrorLogRequest(page){
type: 1, type: 1,
title: "【"+res.domain + "】详情信息", title: "【"+res.domain + "】详情信息",
area: '600px', area: '600px',
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="pd15 lib-box">\ content: '<div class="pd15 lib-box">\
<div style="height:80px;"><table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\ <div style="height:80px;"><table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
@@ -2110,7 +2110,7 @@ laydate.render({
$(this).removeClass('cur'); $(this).removeClass('cur');
}); });
var timeA = value.split('-') var timeA = value.split('-');
var start = $.trim(timeA[0]+'-'+timeA[1]+'-'+timeA[2]) var start = $.trim(timeA[0]+'-'+timeA[1]+'-'+timeA[2])
var end = $.trim(timeA[3]+'-'+timeA[4]+'-'+timeA[5]) var end = $.trim(timeA[3]+'-'+timeA[4]+'-'+timeA[5])
query_txt = toUnixTime(start + " 00:00:00") + "-"+ toUnixTime(end + " 00:00:00") query_txt = toUnixTime(start + " 00:00:00") + "-"+ toUnixTime(end + " 00:00:00")
@@ -2193,12 +2193,37 @@ function wsTableLogRequest(page){
args['search_uri'] = search_uri; args['search_uri'] = search_uri;
args['tojs'] = 'wsTableLogRequest'; args['tojs'] = 'wsTableLogRequest';
var spider_table = {
"1":"百度",
"2":"必应",
"3":"奇虎360",
"4":"Google",
"5":"头条",
"6":"搜狗",
"7":"有道",
"8":"搜搜",
"9":"Dnspod",
"10":"Yandex",
"11":"一搜",
"12":"其他",
}
wsPost('get_logs_list', '' ,args, function(rdata){ wsPost('get_logs_list', '' ,args, function(rdata){
var rdata = $.parseJSON(rdata.data); var rdata = $.parseJSON(rdata.data);
var list = ''; var list = '';
var data = rdata.data.data; var data = rdata.data.data;
if (data.length > 0){ if (data.length > 0){
for(i in data){ for(i in data){
var spider_tip = '';
if (data[i]['is_spider']>0){
spider_tip_name = spider_table[data[i]['is_spider']]
spider_tip = '<div data-toggle="tooltip" title="'+spider_tip_name+'爬虫" style="cursor:pointer;margin:3px;float:left;width:8px;height:8px;line-height:40px;border-radius:50%;background-color:#ccc;"></div>';
}
list += '<tr>'; list += '<tr>';
list += '<td>' + getLocalTime(data[i]['time'])+'</td>'; list += '<td>' + getLocalTime(data[i]['time'])+'</td>';
list += '<td><span class="overflow_hide" style="width:100px;">' + data[i]['domain'] +'</span></td>'; list += '<td><span class="overflow_hide" style="width:100px;">' + data[i]['domain'] +'</span></td>';
@@ -2206,7 +2231,7 @@ function wsTableLogRequest(page){
list += '<td>' + toSize(data[i]['body_length']) +'</td>'; list += '<td>' + toSize(data[i]['body_length']) +'</td>';
list += '<td>' + toSecond(data[i]['request_time']) +'</td>'; list += '<td>' + toSecond(data[i]['request_time']) +'</td>';
list += '<td><span class="overflow_hide" style="width:130px;">' + data[i]['uri'] +'</span></td>'; list += '<td><span class="overflow_hide" style="width:130px;">' + data[i]['uri'] +'</span></td>';
list += '<td><span class="overflow_hide" style="width:60px;">' + data[i]['status_code']+'/' + data[i]['method'] +'</span></td>'; list += '<td>'+spider_tip+'<span class="overflow_hide" style="width:60px;">' + data[i]['status_code']+'/' + data[i]['method'] +'</span></td>';
list += '<td><a data-id="'+i+'" href="javascript:;" class="btlink details" title="详情">详情</a></td>'; list += '<td><a data-id="'+i+'" href="javascript:;" class="btlink details" title="详情">详情</a></td>';
list += '</tr>'; list += '</tr>';
} }
@@ -2241,7 +2266,7 @@ function wsTableLogRequest(page){
type: 1, type: 1,
title: "【"+res.domain + "】详情信息", title: "【"+res.domain + "】详情信息",
area: '600px', area: '600px',
closeBtn: 2, closeBtn: 1,
shadeClose: false, shadeClose: false,
content: '<div class="pd15 lib-box">\ content: '<div class="pd15 lib-box">\
<div style="height:80px;"><table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\ <div style="height:80px;"><table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
@@ -2264,6 +2289,8 @@ function wsTableLogRequest(page){
</div>', </div>',
}); });
}); });
$('[data-toggle="tooltip"]').tooltip();
}); });
} }
@@ -2322,7 +2349,7 @@ var html = '<div>\
<option value="8">搜搜</option>\ <option value="8">搜搜</option>\
<option value="9">Dnspod</option>\ <option value="9">Dnspod</option>\
<option value="10">Yandex</option>\ <option value="10">Yandex</option>\
<option value="12">神马</option>\ <option value="11">一搜</option>\
<option value="12">其他</option>\ <option value="12">其他</option>\
</select>\ </select>\
<span style="margin-left:10px;">URL过滤: </span>\ <span style="margin-left:10px;">URL过滤: </span>\
@@ -2420,11 +2447,3 @@ wsPost('get_default_site','',{},function(rdata){
} }
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+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_today.lua
# $RUN_CMD test_time.lua
# $RUN_CMD test_ngx_find.lua
$RUN_CMD test_match_spider.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)
@@ -0,0 +1,106 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local function match_spider(ua)
-- 匹配蜘蛛请求
local is_spider = false
local spider_name = ""
local spider_match = ""
local spider_table = {
["baidu"] = 1, -- check
["bing"] = 2, -- check
["qh360"] = 3, -- check
["google"] = 4,
["bytes"] = 5, -- check
["sogou"] = 6, -- check
["youdao"] = 7,
["soso"] = 8,
["dnspod"] = 9,
["yandex"] = 10,
["yisou"] = 11,
["other"] = 12,
["mpcrawler"] = 13,
["yahoo"] = 14, -- check
["duckduckgo"] = 15
}
local find_spider, _ = ngx.re.match(ua, "(Baiduspider|Bytespider|360Spider|Sogou web spider|Sosospider|Googlebot|bingbot|AdsBot-Google|Google-Adwords|YoudaoBot|Yandex|DNSPod-Monitor|YisouSpider|mpcrawler)", "ijo")
if find_spider then
is_spider = true
spider_match = string.lower(find_spider[0])
if string.find(spider_match, "baidu", 1, true) then
spider_name = "baidu"
elseif string.find(spider_match, "bytes", 1, true) then
spider_name = "bytes"
elseif string.find(spider_match, "360", 1, true) then
spider_name = "qh360"
elseif string.find(spider_match, "sogou", 1, true) then
spider_name = "sogou"
elseif string.find(spider_match, "soso", 1, true) then
spider_name = "soso"
elseif string.find(spider_match, "google", 1, true) then
spider_name = "google"
elseif string.find(spider_match, "bingbot", 1, true) then
spider_name = "bing"
elseif string.find(spider_match, "youdao", 1, true) then
spider_name = "youdao"
elseif string.find(spider_match, "dnspod", 1, true) then
spider_name = "dnspod"
elseif string.find(spider_match, "yandex", 1, true) then
spider_name = "yandex"
elseif string.find(spider_match, "yisou", 1, true) then
spider_name = "yisou"
elseif string.find(spider_match, "mpcrawler", 1, true) then
spider_name = "mpcrawler"
end
end
if is_spider then
return is_spider, spider_name, spider_table[spider_name]
end
-- Curl|Yahoo|HeadlessChrome|包含bot|Wget|Spider|Crawler|Scrapy|zgrab|python|java|Adsbot|DuckDuckGo
find_spider, _ = ngx.re.match(ua, "(Yahoo|Slurp|DuckDuckGo)", "ijo")
if res then
spider_match = string.lower(find_spider[0])
if string.find(spider_match, "yahoo", 1, true) then
spider_name = "yahoo"
elseif string.find(spider_match, "slurp", 1, true) then
spider_name = "yahoo"
elseif string.find(spider_match, "duckduckgo", 1, true) then
spider_name = "duckduckgo"
end
return true, spider_name, spider_table[spider_name]
end
return false, "", 0
end
-- local is_spider, request_spider, spider_index = match_spider("Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)")
-- ngx.say(is_spider,request_spider, spider_index)
ngx.update_time()
local begin = ngx.now()
local N = 1e6
for i = 1, N do
match_spider("Mozilla/5.0 (compatible; bingbot/2.0; +http://www.bing.com/bingbot.htm)")
end
ngx.update_time()
ngx.say("match_spider elapsed: ", (ngx.now() - begin) / N)
@@ -0,0 +1,35 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local spider_match = "aa 220"
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
ngx.re.find(spider_match, "360", "ijo")
end
ngx.update_time()
ngx.say("ngx.re.find elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e7
for i = 1, N do
string.find(spider_match, "360", 1, true)
end
ngx.update_time()
ngx.say("string.find elapsed: ", (ngx.now() - begin) / N)
+118
View File
@@ -0,0 +1,118 @@
local function target()
ngx.re.find("hello, world.", [[\w+\.]], "jo")
end
for i = 1, 100 do
target()
end
-- 以上为预热操作
collectgarbage()
local function get_store_key()
return os.date("%Y%m%d%H", os.time())
end
local function get_store_key2()
return os.date("%Y%m%d%H", ngx.time())
end
local function get_end_time()
local s_time = os.time()
local n_date = os.date("*t",s_time + 86400)
n_date.hour = 0
n_date.min = 0
n_date.sec = 0
local d_time = os.time(n_date)
return d_time - s_time
end
local function get_end_time2()
local s_time = ngx.time()
local n_date = os.date("*t",s_time + 86400)
n_date.hour = 0
n_date.min = 0
n_date.sec = 0
local d_time = ngx.time(n_date)
return d_time - s_time
end
local function get_update_field(field, value)
return field.."="..field.."+"..value
end
local function get_update_field2(field, value)
return field.."="..field.."+"..tostring(value)
end
ngx.update_time()
local begin = ngx.now()
local N = 1e3
for i = 1, N do
get_store_key()
end
ngx.update_time()
ngx.say("get_store_key elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e3
for i = 1, N do
get_store_key2()
end
ngx.update_time()
ngx.say("get_store_key2 elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e5
for i = 1, N do
get_end_time()
end
ngx.update_time()
ngx.say("get_end_time elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e5
for i = 1, N do
get_end_time2()
end
ngx.update_time()
ngx.say("get_end_time2 elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e9
for i = 1, N do
get_update_field("ss","1")
end
ngx.update_time()
ngx.say("get_update_field elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e9
for i = 1, N do
get_update_field2("ss",1)
end
ngx.update_time()
ngx.say("get_update_field2 elapsed: ", (ngx.now() - begin) / N)
+33
View File
@@ -0,0 +1,33 @@
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 = 1e6
for i = 1, N do
os.date("%Y%m%d")
-- ngx.say(t)
end
ngx.update_time()
ngx.say("os.date elapsed: ", (ngx.now() - begin) / N)
ngx.update_time()
local begin = ngx.now()
local N = 1e6
for i = 1, N do
ngx.re.gsub(ngx.today(),'-','')
-- ngx.say(t)
end
ngx.update_time()
ngx.say("ngx.today() elapsed: ", (ngx.now() - begin) / N)
+122
View File
@@ -0,0 +1,122 @@
# 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 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 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 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 test_OK():
'''
目录保存
'''
url = TEST_URL + "ok.txt"
print("ok test start")
url_val = httpGet__UA(
url, "Mozilla / 5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit / 537.36 (KHTML, like Gecko) Chrome/106.0.0.0 Safari/537.36")
print(url_val)
print("ok test end")
def test_Spider():
'''
目录保存
'''
url = TEST_URL + "ok.txt"
print("spider test start")
url_val = httpGet__UA(
url, "Mozilla/5.0 (Linux; Android 6.0.1; Nexus 5X Build/MMB29P) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/106.0.5249.103 Mobile Safari/537.36 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
print(url_val)
print("spider test end")
def test_start():
test_OK()
test_Spider()
if __name__ == "__main__":
os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/webstats && 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()
+6
View File
@@ -0,0 +1,6 @@
#!/bin/bash
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
export PATH
python3 index.py
+21 -19
View File
@@ -107,7 +107,7 @@ function getSList(isdisplay) {
var mupdate = '';//(plugin.versions[n] == plugin.updates[n]) '' : '<a class="btlink" onclick="softUpdate(\'' + plugin.name + '\',\'' + plugin.versions[n].version + '\',\'' + plugin.updates[n] + '\')">更新</a> | '; var mupdate = '';//(plugin.versions[n] == plugin.updates[n]) '' : '<a class="btlink" onclick="softUpdate(\'' + plugin.name + '\',\'' + plugin.versions[n].version + '\',\'' + plugin.updates[n] + '\')">更新</a> | ';
// if (plugin.versions[n] == '') mupdate = ''; // if (plugin.versions[n] == '') mupdate = '';
handle = mupdate + '<a class="btlink" onclick="softMain(\'' + plugin.name + '\',\'' + plugin.title + '\',\'' + plugin.setup_version + '\')">设置</a> | <a class="btlink" onclick="uninstallVersion(\'' + plugin.name + '\',\'' + plugin.setup_version + '\',' + plugin.uninstall_pre_inspection +')">卸载</a>'; handle = mupdate + '<a class="btlink" onclick="softMain(\'' + plugin.name + '\',\'' + plugin.title + '\',\'' + plugin.setup_version + '\')">设置</a> | <a class="btlink" onclick="uninstallVersion(\'' + plugin.name + '\',\'' + plugin.title +'\',\'' + plugin.setup_version + '\',' + plugin.uninstall_pre_inspection +')">卸载</a>';
titleClick = 'onclick="softMain(\'' + plugin.name + '\',\'' + plugin.title + '\',\'' + plugin.setup_version + '\')" style="cursor:pointer"'; titleClick = 'onclick="softMain(\'' + plugin.name + '\',\'' + plugin.title + '\',\'' + plugin.setup_version + '\')" style="cursor:pointer"';
softPath = '<span class="glyphicon glyphicon-folder-open" title="' + plugin.path + '" onclick="openPath(\'' + plugin.path + '\')"></span>'; softPath = '<span class="glyphicon glyphicon-folder-open" title="' + plugin.path + '" onclick="openPath(\'' + plugin.path + '\')"></span>';
@@ -189,7 +189,7 @@ function runInstall(data){
function addVersion(name, ver, type, obj, title, install_pre_inspection) { function addVersion(name, ver, type, obj, title, install_pre_inspection) {
var option = ''; var option = '';
var titlename = name; var titlename = title.replace("-"+ver,"");
if (ver.indexOf('|') >= 0){ if (ver.indexOf('|') >= 0){
var veropt = ver.split("|"); var veropt = ver.split("|");
var selectVersion = ''; var selectVersion = '';
@@ -198,12 +198,12 @@ function addVersion(name, ver, type, obj, title, install_pre_inspection) {
} }
option = "<select id='selectVersion' class='bt-input-text' style='margin-left:30px'>" + selectVersion + "</select>"; option = "<select id='selectVersion' class='bt-input-text' style='margin-left:30px'>" + selectVersion + "</select>";
} else { } else {
option = '<span id="selectVersion">' + name + ' ' + ver + '</span>'; option = '<span id="selectVersion" val="' + name + ' ' + ver + '">【' + titlename + '】 ' + ver + '</span>';
} }
layer.open({ layer.open({
type: 1, type: 1,
title: titlename + "软件安装", title: "【"+titlename + "】软件安装",
area: '350px', area: '350px',
closeBtn: 1, closeBtn: 1,
shadeClose: true, shadeClose: true,
@@ -218,27 +218,28 @@ function addVersion(name, ver, type, obj, title, install_pre_inspection) {
installTips(); installTips();
}, },
yes:function(index,layero){ yes:function(index,layero){
// console.log(index,layero)
var info = $("#selectVersion").val().toLowerCase(); var info = $("#selectVersion").val().toLowerCase();
if (info == ''){ if (info == ''){
info = $("#selectVersion").text().toLowerCase(); info = $("#selectVersion").attr('val').toLowerCase();
} }
var name = info.split(" ")[0]; var info_split = info.split(' ');
var version = info.split(" ")[1]; var name = info_split[0];
var version = info_split[1];
var type = $('.fangshi').prop("checked") ? '1' : '0'; var type = $('.fangshi').prop("checked") ? '1' : '0';
var data = "name=" + name + "&version=" + version + "&type=" + type; var request_args = "name=" + name + "&version=" + version + "&type=" + type;
// console.log(data);
if (install_pre_inspection){ if (install_pre_inspection){
//安装检查 //安装检查
installPreInspection(name, version, function(){ installPreInspection(name, version, function(){
runInstall(data); runInstall(request_args);
flySlow('layui-layer-btn0'); flySlow('layui-layer-btn0');
}); });
return; return;
} }
runInstall(data);
runInstall(request_args);
flySlow('layui-layer-btn0'); flySlow('layui-layer-btn0');
} }
}); });
} }
@@ -261,8 +262,9 @@ function uninstallPreInspection(name, ver, callback){
} }
function runUninstallVersion(name, version){ function runUninstallVersion(name, title, version){
layer.confirm(msgTpl('您真的要卸载[{1}-{2}]吗?', [name, version]), { icon: 3, closeBtn: 1 }, function() { var title = title.replace("-"+version,"");
layer.confirm(msgTpl('您真的要卸载【{1}-{2}】吗?', [title, version]), { icon: 3, closeBtn: 1 }, function() {
var data = 'name=' + name + '&version=' + version; var data = 'name=' + name + '&version=' + version;
var loadT = layer.msg('正在处理,请稍候...', { icon: 16, time: 0, shade: [0.3, '#000'] }); var loadT = layer.msg('正在处理,请稍候...', { icon: 16, time: 0, shade: [0.3, '#000'] });
$.post('/plugins/uninstall', data, function(rdata) { $.post('/plugins/uninstall', data, function(rdata) {
@@ -274,14 +276,14 @@ function runUninstallVersion(name, version){
} }
function uninstallVersion(name, version,uninstall_pre_inspection) { function uninstallVersion(name, title, version, uninstall_pre_inspection) {
if (uninstall_pre_inspection) { if (uninstall_pre_inspection) {
uninstallPreInspection(name,version,function(){ uninstallPreInspection(name,title,version,function(){
runUninstallVersion(name,version); runUninstallVersion(name,title,version);
}); });
return; return;
} }
runUninstallVersion(name,version); runUninstallVersion(name,title,version);
} }

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