mirror of
https://github.com/midoks/mdserver-web.git
synced 2026-10-12 07:29:27 +08:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9b83a2ef79 | ||
|
|
6aefa3b7dc | ||
|
|
566fabbf24 | ||
|
|
ea8aa5102b | ||
|
|
b8421d36ae | ||
|
|
24bd8daca0 | ||
|
|
d8047b43fa | ||
|
|
016dde04e7 | ||
|
|
df5d86a883 | ||
|
|
84077de5d1 | ||
|
|
04ed4b180a | ||
|
|
f980dba7ed | ||
|
|
f702f70f89 | ||
|
|
a8e6ee052c | ||
|
|
b3d0a36dcd | ||
|
|
96275303c6 | ||
|
|
0337a1bded | ||
|
|
8bd985fca9 | ||
|
|
b6ef8d1625 | ||
|
|
3dc695508f | ||
|
|
0c769b02e5 | ||
|
|
e289037598 | ||
|
|
63e6a95553 | ||
|
|
8e1d95bf82 | ||
|
|
24fe8b6f5f | ||
|
|
3d366ee774 | ||
|
|
0428956141 | ||
|
|
37747427be | ||
|
|
fb94fb8304 | ||
|
|
65d07d3934 | ||
|
|
5e6ffafeb5 | ||
|
|
572f231fae | ||
|
|
0328dd21e7 | ||
|
|
597d171733 | ||
|
|
745ab9dcd0 | ||
|
|
30323b031c | ||
|
|
f47e6a47df | ||
|
|
0eccebd9da | ||
|
|
0ad5e74fae | ||
|
|
2640ba97c5 | ||
|
|
e5f440ff02 | ||
|
|
7bc9c44ec1 | ||
|
|
9cd74db011 | ||
|
|
5da8e5a7f6 | ||
|
|
4da895b8df | ||
|
|
42eca14168 | ||
|
|
43a3dfd9bd | ||
|
|
794eba4186 | ||
|
|
a4f533acba | ||
|
|
adb3c5250c | ||
|
|
e4226fcdd4 | ||
|
|
d3e9353589 | ||
|
|
757284cdf1 | ||
|
|
58232e10ab | ||
|
|
fde211e026 | ||
|
|
c9a527e487 | ||
|
|
c501efdfac | ||
|
|
80c0bbed71 | ||
|
|
1fb3c30775 | ||
|
|
24ab203770 | ||
|
|
bd0242db2f | ||
|
|
42bf5edd1f | ||
|
|
7b2a011b6a | ||
|
|
76e01201a2 | ||
|
|
16e45cabfc | ||
|
|
c08542ff54 | ||
|
|
5beb76d0b7 | ||
|
|
f16a7e016e | ||
|
|
eb86ac3ee6 | ||
|
|
14c2606532 | ||
|
|
86b8939cb8 | ||
|
|
dd28c1ef56 | ||
|
|
6b24dfc21e | ||
|
|
dc06573125 | ||
|
|
df35e5a780 | ||
|
|
a678d851a0 | ||
|
|
6a706651e4 | ||
|
|
1acdfe4368 | ||
|
|
cae245efca | ||
|
|
238f1e76d8 | ||
|
|
f3a754d1ae | ||
|
|
21aab0573a | ||
|
|
011949ba85 | ||
|
|
f3e7dd1cc0 | ||
|
|
b49d2025eb | ||
|
|
556b0869f2 | ||
|
|
aad6deeb78 | ||
|
|
64601e42c1 | ||
|
|
6555d927ea | ||
|
|
444ff40570 | ||
|
|
7bdcd0ac2b | ||
|
|
6e6a41e6df | ||
|
|
feca2a6d33 | ||
|
|
5e382e7347 | ||
|
|
abc778fb52 | ||
|
|
6b42d35cd4 | ||
|
|
c74a2c9655 | ||
|
|
01543f951a | ||
|
|
d78a5d8f27 | ||
|
|
2a1d759cd2 | ||
|
|
43889f83f7 | ||
|
|
79a0a93959 | ||
|
|
735cf9b872 | ||
|
|
e7c318e560 | ||
|
|
78d03754f6 | ||
|
|
67cc1cac86 | ||
|
|
77ec90980a | ||
|
|
d07b2babfd | ||
|
|
4d9ee94038 | ||
|
|
61479d5db6 | ||
|
|
897c28034d | ||
|
|
b3fef4c104 | ||
|
|
48cec8ee47 | ||
|
|
7c369ef19f | ||
|
|
1411bb1639 | ||
|
|
be875d9d8c | ||
|
|
746dc7ee4d | ||
|
|
ea7ba7d461 | ||
|
|
48ed4156b5 | ||
|
|
ca73d0e280 | ||
|
|
8cef43d9a7 | ||
|
|
75445774a1 | ||
|
|
9b29f19b96 | ||
|
|
1e6655e7f9 | ||
|
|
363656e06c | ||
|
|
a1860bc4fc | ||
|
|
f8ce39bc74 | ||
|
|
969d02ef93 | ||
|
|
a54410df6e | ||
|
|
01e388ea45 | ||
|
|
ef75f22a86 | ||
|
|
97f6b232fd | ||
|
|
2506f5e940 | ||
|
|
dcb23ada41 | ||
|
|
35e1bf048c | ||
|
|
a9e24f8eaf | ||
|
|
2f4ac74f52 | ||
|
|
522122feb6 | ||
|
|
a3c677a926 | ||
|
|
fd1c52530e | ||
|
|
071c690583 | ||
|
|
67c9cd0277 | ||
|
|
61292868ad | ||
|
|
54b2a00b23 | ||
|
|
af6d377664 | ||
|
|
6d55e345b0 | ||
|
|
fab4e68d8d | ||
|
|
8864e91f21 | ||
|
|
f14ce1b66c | ||
|
|
48098efd56 | ||
|
|
04eba8e33f | ||
|
|
89cf7ffafc | ||
|
|
47544520e8 | ||
|
|
bc1fd9a8af | ||
|
|
27efc7ef6e | ||
|
|
47ead816c0 | ||
|
|
31d36182c3 | ||
|
|
c9a58c7ea5 | ||
|
|
a6e59ae37c | ||
|
|
328e1b0ff1 | ||
|
|
f76cc5ceb8 | ||
|
|
d6c74c3f7d | ||
|
|
4f932c36e7 | ||
|
|
0d02d0ebea | ||
|
|
9e207ad4d3 | ||
|
|
f6cfe29956 | ||
|
|
e439111761 | ||
|
|
e576d0b443 | ||
|
|
02e2c42225 | ||
|
|
45dec0a3d6 | ||
|
|
28e2abc829 | ||
|
|
d59c82b7c8 | ||
|
|
32b2158795 | ||
|
|
5a37305c73 | ||
|
|
c043963e8e | ||
|
|
40d755b44e | ||
|
|
00aa791205 | ||
|
|
431b3646af | ||
|
|
910aaa81de | ||
|
|
c4a844cadb | ||
|
|
a88a281175 | ||
|
|
f3f3b1c6bd | ||
|
|
4259ac51cb | ||
|
|
4db1357d3d | ||
|
|
15873e0824 | ||
|
|
dcdb07f76d | ||
|
|
8b70637479 | ||
|
|
c77085fea4 | ||
|
|
a265f3d0d5 | ||
|
|
7ea486cd1d | ||
|
|
0e31e87e28 | ||
|
|
8c621c892e | ||
|
|
32bcae603c | ||
|
|
98ec21446d | ||
|
|
0ee3682502 | ||
|
|
c609d1a012 | ||
|
|
27b1a78879 | ||
|
|
773de840a5 | ||
|
|
91d6ff3c54 | ||
|
|
03376bd42d | ||
|
|
036c5114c2 | ||
|
|
a772e70fde | ||
|
|
53055bbdef | ||
|
|
f81d598fcf | ||
|
|
3530e83bb9 | ||
|
|
1271b2f637 | ||
|
|
2dc6bc7753 | ||
|
|
e52d9e3ea3 | ||
|
|
d8a570e55e | ||
|
|
f4ceaf667b | ||
|
|
958ba16b85 | ||
|
|
73039777bb | ||
|
|
864e4c910c | ||
|
|
4da57405af | ||
|
|
dff638571a | ||
|
|
c7d9ec51cc | ||
|
|
501c575f73 | ||
|
|
0fd966ca65 | ||
|
|
172dde2794 | ||
|
|
78fdc80652 | ||
|
|
01b8c9b8ff | ||
|
|
b840086d4d | ||
|
|
4c73f13f2d | ||
|
|
f31c1aae96 | ||
|
|
5c24a831db | ||
|
|
91d07eebad | ||
|
|
3b51ef2434 | ||
|
|
31c5e42b09 | ||
|
|
b8b3a237ef | ||
|
|
5cb2aefbbc | ||
|
|
19173af3e2 | ||
|
|
3dc493108b | ||
|
|
55af62000b | ||
|
|
a1c8c48761 | ||
|
|
8c3ec0a103 | ||
|
|
5cbde31105 | ||
|
|
04dd94032e | ||
|
|
8a11195b0d | ||
|
|
1eb76baae7 | ||
|
|
2669d6f021 | ||
|
|
6f13a03a2c |
@@ -0,0 +1,5 @@
|
||||
# These are supported funding model platforms
|
||||
|
||||
github: midoks
|
||||
|
||||
custom: https://afdian.net/a/mdserver-web
|
||||
@@ -65,6 +65,8 @@ phpMyAdmin[5.2.0]支持MySQL[8.0]
|
||||
|
||||
PHP[53-72]支持phpMyAdmin[4.4.15]
|
||||
PHP[72-81]支持phpMyAdmin[5.2.0]
|
||||
|
||||
|
||||
```
|
||||
|
||||
# 特别赞助
|
||||
@@ -78,7 +80,7 @@ PHP[72-81]支持phpMyAdmin[5.2.0]
|
||||
| 服务商 | LOGO | 推广地址 | 优惠码 |
|
||||
| ------------- |----------|-----------|-------|
|
||||
| digitalvirt |[](https://digitalvirt.com/aff.php?aff=154) | https://digitalvirt.com/aff.php?aff=154 | 9SYDY7UH0U |
|
||||
| 搬瓦工 |[](https://bandwagonhost.com/aff.php?aff=54161) | https://bandwagonhost.com/aff.php?aff=54161 | BWH3HYATVBJW |
|
||||
| 搬瓦工 |[](https://bwh81.net/aff.php?aff=54161) | https://bwh81.net/aff.php?aff=54161 | BWH3HYATVBJW |
|
||||
|
||||
# Docker
|
||||
|
||||
@@ -90,16 +92,11 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
|
||||
```
|
||||
|
||||
|
||||
### 版本更新 0.9.12
|
||||
|
||||
* 日志清理插件优化。
|
||||
* 计划任务显示完整。
|
||||
* 加入gitea插件。
|
||||
* 融合mw-cli命令。
|
||||
* 加快php编译速度。
|
||||
* swap加上调整功能。
|
||||
* 其他细节优化。
|
||||
### 版本更新 0.9.14
|
||||
|
||||
* 优化网站统计插件,提搞速度和并发数。
|
||||
* mysql8安装地址更新。
|
||||
* OP防火墙优化。
|
||||
|
||||
### JSDelivr安装地址
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ from flask import request
|
||||
|
||||
class config_api:
|
||||
|
||||
__version = '0.9.12'
|
||||
__version = '0.9.14'
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
+11
-4
@@ -161,19 +161,24 @@ def isInstalledWeb():
|
||||
|
||||
|
||||
def restartWeb():
|
||||
return opWeb("reload")
|
||||
|
||||
|
||||
def opWeb(method):
|
||||
if not isInstalledWeb():
|
||||
return False
|
||||
|
||||
# systemd
|
||||
systemd = '/lib/systemd/system/openresty.service'
|
||||
if os.path.exists(systemd):
|
||||
execShell('systemctl reload openresty')
|
||||
execShell('systemctl ' + method + ' openresty')
|
||||
return True
|
||||
|
||||
# initd
|
||||
initd = getServerDir() + '/openresty/init.d/openresty'
|
||||
|
||||
if os.path.exists(initd):
|
||||
execShell(initd + ' ' + 'reload')
|
||||
execShell(initd + ' ' + method)
|
||||
return True
|
||||
|
||||
return False
|
||||
@@ -595,12 +600,14 @@ def getLastLine(path, num, p=1):
|
||||
count = start_line + num
|
||||
fp = open(path, 'rb')
|
||||
buf = ""
|
||||
fp.seek(-1, 2)
|
||||
|
||||
fp.seek(0, 2)
|
||||
if fp.read(1) == "\n":
|
||||
fp.seek(-1, 2)
|
||||
fp.seek(0, 2)
|
||||
data = []
|
||||
b = True
|
||||
n = 0
|
||||
|
||||
for i in range(count):
|
||||
while True:
|
||||
newline_pos = str.rfind(str(buf), "\n")
|
||||
|
||||
@@ -98,6 +98,7 @@ def initConf():
|
||||
"/var/log/secure",
|
||||
"/var/log/lastlog",
|
||||
"/var/log/cron",
|
||||
"/www/server/cron"
|
||||
]
|
||||
for i in clogcom:
|
||||
if os.path.exists(i):
|
||||
|
||||
@@ -23,8 +23,6 @@ Install_app()
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
mkdir -p $serverPath/clean
|
||||
|
||||
echo "" > $serverPath/clean/clean.conf
|
||||
|
||||
cd ${rootPath} && python3 ${rootPath}/plugins/clean/index.py start
|
||||
echo "${VERSION}" > $serverPath/clean/version.pl
|
||||
echo '安装完成' > $install_tmp
|
||||
|
||||
@@ -88,16 +88,18 @@ def createBgTaskByName(name, args):
|
||||
_where1 = args['minute-n']
|
||||
_minute = ''
|
||||
|
||||
mw_dir = mw.getRunDir()
|
||||
cmd = '''
|
||||
mw_dir=%s
|
||||
rname=%s
|
||||
plugin_path=%s
|
||||
script_path=%s
|
||||
logs_file=$plugin_path/${rname}.log
|
||||
''' % (name, getServerDir(), getPluginDir())
|
||||
''' % (mw_dir, name, getServerDir(), getPluginDir())
|
||||
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
|
||||
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
|
||||
cmd += 'echo "python3 $script_path/index.py clean >> $logs_file 2>&1"' + "\n"
|
||||
cmd += 'python3 $script_path/index.py clean >> $logs_file 2>&1' + "\n"
|
||||
cmd += 'cd $mw_dir && python3 $script_path/index.py clean >> $logs_file 2>&1' + "\n"
|
||||
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
|
||||
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
|
||||
|
||||
|
||||
@@ -817,6 +817,7 @@ function openPhpmyadmin(name,username,password){
|
||||
layer.msg('当前为['+rdata.choose+']模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
var phpmyadmin_cfg = rdata;
|
||||
|
||||
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'});
|
||||
var rdata = $.parseJSON(data.data);
|
||||
@@ -824,7 +825,10 @@ function openPhpmyadmin(name,username,password){
|
||||
layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
$("#toPHPMyAdmin").attr('action',rdata.data);
|
||||
|
||||
var home_page = rdata.data;
|
||||
home_page = home_page.replace("http://","http://"+phpmyadmin_cfg['username']+":"+phpmyadmin_cfg['password']+"@");
|
||||
$("#toPHPMyAdmin").attr('action',home_page);
|
||||
|
||||
if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){
|
||||
layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']});
|
||||
|
||||
@@ -80,7 +80,8 @@ innodb_data_home_dir = {$SERVER_APP_PATH}/data
|
||||
innodb_data_file_path = ibdata1:10M:autoextend
|
||||
innodb_log_group_home_dir = {$SERVER_APP_PATH}/data
|
||||
innodb_buffer_pool_size = 16M
|
||||
innodb_log_file_size = 5M
|
||||
#innodb_log_file_size = 5M
|
||||
innodb_redo_log_capacity=10485760
|
||||
innodb_log_buffer_size = 8M
|
||||
innodb_flush_log_at_trx_commit = 2
|
||||
innodb_lock_wait_timeout = 120
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"path": "server/mysql/VERSION",
|
||||
"todo_versions":["5.6","5.7","8.0"],
|
||||
"versions":["5.5", "5.6", "5.7","8.0"],
|
||||
"updates":["5.5.62","5.6.50", "5.7.32","8.0.22"],
|
||||
"updates":["5.5.62","5.6.50", "5.7.32","8.0.30"],
|
||||
"shell":"install.sh",
|
||||
"checks":"server/mysql",
|
||||
"path":"server/mysql",
|
||||
|
||||
@@ -68,6 +68,26 @@ function myAsyncPost(method,args){
|
||||
return syncPost('/plugins/run', {name:'mysql', func:method, args:_args});
|
||||
}
|
||||
|
||||
function vaildPhpmyadmin(url,username,password){
|
||||
|
||||
console.log("Authorization: Basic " + btoa(username + ":" + password));
|
||||
$.ajax({
|
||||
type: "GET",
|
||||
url: url,
|
||||
dataType: 'json',
|
||||
async: false,
|
||||
username:username,
|
||||
password:password,
|
||||
headers: {
|
||||
"Authorization": "Basic " + btoa(username + ":" + password)
|
||||
},
|
||||
data: 'vaild',
|
||||
success: function (){
|
||||
alert('Thanks for your comment!');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function runInfo(){
|
||||
myPost('run_info','',function(data){
|
||||
|
||||
@@ -818,16 +838,19 @@ function openPhpmyadmin(name,username,password){
|
||||
layer.msg('当前为[mariadb]模式,若要使用请切换模式.',{icon:2,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
|
||||
// console.log(data);
|
||||
|
||||
var phpmyadmin_cfg = rdata;
|
||||
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'get_home_page'});
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (!rdata.status){
|
||||
layer.msg(rdata.msg,{icon:2,shade: [0.3, '#000']});
|
||||
return;
|
||||
}
|
||||
$("#toPHPMyAdmin").attr('action',rdata.data);
|
||||
var home_page = rdata.data;
|
||||
|
||||
home_page = home_page.replace("http://","http://"+phpmyadmin_cfg['username']+":"+phpmyadmin_cfg['password']+"@")
|
||||
|
||||
$("#toPHPMyAdmin").attr('action',home_page);
|
||||
if($("#toPHPMyAdmin").attr('action').indexOf('phpmyadmin') == -1){
|
||||
layer.msg('请先安装phpMyAdmin',{icon:2,shade: [0.3, '#000']});
|
||||
setTimeout(function(){ window.location.href = '/soft'; },3000);
|
||||
@@ -836,7 +859,7 @@ function openPhpmyadmin(name,username,password){
|
||||
|
||||
//检查版本
|
||||
data = syncPost('/plugins/run',{'name':'phpmyadmin','func':'version'});
|
||||
bigVer = data.data.split('.')[0]
|
||||
bigVer = data.data.split('.')[0];
|
||||
if (bigVer>=4.5){
|
||||
|
||||
setTimeout(function(){
|
||||
|
||||
@@ -17,7 +17,7 @@ sysName=`uname`
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
mysqlDir=${serverPath}/source/mysql
|
||||
|
||||
VERSION="5.7.37"
|
||||
VERSION=5.7.39
|
||||
|
||||
|
||||
Install_mysql()
|
||||
@@ -64,11 +64,11 @@ Install_mysql()
|
||||
cd ${rootPath}/plugins/mysql/lib && /bin/bash rpcgen.sh
|
||||
|
||||
if [ ! -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
|
||||
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-boost-${VERSION}.tar.gz
|
||||
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-5.7/mysql-boost-${VERSION}.tar.gz
|
||||
fi
|
||||
|
||||
#检测文件是否损坏.
|
||||
md5_mysql_ok=d0489fc3880248a58759c50bfb286dbb
|
||||
md5_mysql_ok=d949b0ef81c3f52f7ef0874066244221
|
||||
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
|
||||
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
|
||||
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then
|
||||
@@ -76,7 +76,7 @@ Install_mysql()
|
||||
else
|
||||
# 重新下载
|
||||
rm -rf ${mysqlDir}/mysql-${VERSION}
|
||||
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-5.7/mysql-boost-${VERSION}.tar.gz
|
||||
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-5.7/mysql-boost-${VERSION}.tar.gz
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ fi
|
||||
VERSION_ID=`cat /etc/*-release | grep VERSION_ID | awk -F = '{print $2}' | awk -F "\"" '{print $2}'`
|
||||
|
||||
|
||||
VERSION=8.0.28
|
||||
VERSION=8.0.30
|
||||
Install_mysql()
|
||||
{
|
||||
mkdir -p ${mysqlDir}
|
||||
@@ -107,11 +107,11 @@ Install_mysql()
|
||||
fi
|
||||
|
||||
if [ ! -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
|
||||
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-8.0/mysql-boost-${VERSION}.tar.gz
|
||||
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-8.0/mysql-boost-${VERSION}.tar.gz
|
||||
fi
|
||||
|
||||
#检测文件是否损坏.
|
||||
md5_mysql_ok=362b8141ecaf425b803fe55292e2df98
|
||||
md5_mysql_ok=313d625fcaa932bd87b48f0cf9b40f1c
|
||||
if [ -f ${mysqlDir}/mysql-boost-${VERSION}.tar.gz ];then
|
||||
md5_mysql=`md5sum ${mysqlDir}/mysql-boost-${VERSION}.tar.gz | awk '{print $1}'`
|
||||
if [ "${md5_mysql_ok}" == "${md5_mysql}" ]; then
|
||||
@@ -119,7 +119,7 @@ Install_mysql()
|
||||
else
|
||||
# 重新下载
|
||||
rm -rf ${mysqlDir}/mysql-${VERSION}
|
||||
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/Downloads/MySQL-8.0/mysql-boost-${VERSION}.tar.gz
|
||||
wget -O ${mysqlDir}/mysql-boost-${VERSION}.tar.gz --tries=3 https://cdn.mysql.com/archives/mysql-8.0/mysql-boost-${VERSION}.tar.gz
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
@@ -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")
|
||||
@@ -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
|
||||
);
|
||||
@@ -1,8 +1,10 @@
|
||||
lua_shared_dict limit 30m;
|
||||
lua_shared_dict drop_ip 30m;
|
||||
lua_shared_dict drop_sum 30m;
|
||||
lua_package_path "{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;";
|
||||
lua_shared_dict waf_limit 30m;
|
||||
lua_shared_dict waf_drop_ip 10m;
|
||||
lua_shared_dict waf_drop_sum 10m;
|
||||
lua_package_path "{$WAF_PATH}/html/?.lua;{$WAF_PATH}/conf/?.lua;{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;";
|
||||
lua_package_cpath "{$WAF_PATH}/conf/?.so;{$ROOT_PATH}/openresty/lualib/?.so;;";
|
||||
|
||||
init_worker_by_lua_file {$WAF_PATH}/lua/init_worker.lua;
|
||||
access_by_lua_file {$WAF_PATH}/lua/init.lua;
|
||||
|
||||
#init_by_lua_file {$WAF_PATH}/lua/init.lua;
|
||||
#access_by_lua_file {$WAF_PATH}/lua/waf.lua;
|
||||
# init_by_lua_file {$WAF_PATH}/lua/init.lua;
|
||||
|
||||
@@ -1,4 +1,18 @@
|
||||
<style>
|
||||
|
||||
.overflow_hide {
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
.cur {
|
||||
background-color: #20a53a;
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
/*waf*/
|
||||
.lib-con-title {
|
||||
height: 26px;
|
||||
@@ -231,8 +245,8 @@
|
||||
<p onclick="wafScreen();">首页</p>
|
||||
<p onclick="wafGloabl();">全局配置</p>
|
||||
<p onclick="wafSite();">站点配置</p>
|
||||
<p onclick="wafHistory();">封锁历史</p>
|
||||
<!-- <p onclick="wafLogs();">操作日志</p> -->
|
||||
<p onclick="wafLogs();">封锁历史</p>
|
||||
<!-- <p onclick="wafOpLogs();">操作日志</p> -->
|
||||
</div>
|
||||
<!-- lib-con -->
|
||||
<div class="bt-w-con pd15">
|
||||
|
||||
+295
-27
@@ -52,11 +52,50 @@ def checkArgs(data, ck=[]):
|
||||
return (True, mw.returnJson(True, 'ok'))
|
||||
|
||||
|
||||
sys.path.append(getPluginDir() + "/class")
|
||||
from luamaker import luamaker
|
||||
|
||||
|
||||
def listToLuaFile(path, lists):
|
||||
content = luamaker.makeLuaTable(lists)
|
||||
content = "return " + content
|
||||
mw.writeFile(path, content)
|
||||
|
||||
|
||||
def htmlToLuaFile(path, content):
|
||||
content = "return [[" + content + "]]"
|
||||
mw.writeFile(path, content)
|
||||
|
||||
|
||||
def getConf():
|
||||
path = mw.getServerDir() + "/openresty/nginx/conf/nginx.conf"
|
||||
return path
|
||||
|
||||
|
||||
def pSqliteDb(dbname='logs'):
|
||||
name = "waf"
|
||||
db_dir = getServerDir() + '/logs/'
|
||||
|
||||
if not os.path.exists(db_dir):
|
||||
mw.execShell('mkdir -p ' + db_dir)
|
||||
|
||||
file = db_dir + name + '.db'
|
||||
if not os.path.exists(file):
|
||||
conn = mw.M(dbname).dbPos(db_dir, name)
|
||||
sql = mw.readFile(getPluginDir() + '/conf/init.sql')
|
||||
sql_list = sql.split(';')
|
||||
for index in range(len(sql_list)):
|
||||
conn.execute(sql_list[index])
|
||||
else:
|
||||
conn = mw.M(dbname).dbPos(db_dir, name)
|
||||
|
||||
conn.execute("PRAGMA synchronous = 0")
|
||||
conn.execute("PRAGMA page_size = 4096")
|
||||
conn.execute("PRAGMA journal_mode = wal")
|
||||
conn.execute("PRAGMA journal_size_limit = 1073741824")
|
||||
return conn
|
||||
|
||||
|
||||
def initDomainInfo():
|
||||
data = []
|
||||
path_domains = getJsonPath('domains')
|
||||
@@ -111,7 +150,7 @@ def initSiteInfo():
|
||||
tmp['log'] = True
|
||||
tmp['get'] = True
|
||||
tmp['post'] = True
|
||||
tmp['open'] = False
|
||||
tmp['open'] = True
|
||||
|
||||
tmp['cc'] = config_contents['cc']
|
||||
tmp['retry'] = config_contents['retry']
|
||||
@@ -120,9 +159,24 @@ def initSiteInfo():
|
||||
tmp['user-agent'] = config_contents['user-agent']
|
||||
tmp['cookie'] = config_contents['cookie']
|
||||
tmp['scan'] = config_contents['scan']
|
||||
tmp['safe_verify'] = config_contents['safe_verify']
|
||||
|
||||
cdn_header = ['x-forwarded-for',
|
||||
'x-real-ip', 'HTTP_CF_CONNECTING_IP']
|
||||
'x-real-ip',
|
||||
'x-forwarded',
|
||||
'forwarded-for',
|
||||
'forwarded',
|
||||
'true-client-ip',
|
||||
'client-ip',
|
||||
'ali-cdn-real-ip',
|
||||
'cdn-src-ip',
|
||||
'cdn-real-ip',
|
||||
'cf-connecting-ip',
|
||||
'x-cluster-client-ip',
|
||||
'wl-proxy-client-ip',
|
||||
'proxy-client-ip',
|
||||
'true-client-ip',
|
||||
'HTTP_CF_CONNECTING_IP']
|
||||
tmp['cdn_header'] = cdn_header
|
||||
|
||||
disable_upload_ext = ["php", "jsp"]
|
||||
@@ -163,6 +217,9 @@ def initTotalInfo():
|
||||
tmp['get'] = 0
|
||||
tmp['post'] = 0
|
||||
tmp['total'] = 0
|
||||
tmp['path'] = 0
|
||||
tmp['php_path'] = 0
|
||||
tmp['upload_ext'] = 0
|
||||
_name = {}
|
||||
_name[name] = tmp
|
||||
total_contents['sites'] = _name
|
||||
@@ -186,21 +243,109 @@ def status():
|
||||
|
||||
def contentReplace(content):
|
||||
service_path = mw.getServerDir()
|
||||
waf_path = getServerDir() + "/waf"
|
||||
waf_root = getServerDir()
|
||||
waf_path = waf_root + "/waf"
|
||||
content = content.replace('{$ROOT_PATH}', mw.getRootDir())
|
||||
content = content.replace('{$SERVER_PATH}', service_path)
|
||||
content = content.replace('{$WAF_PATH}', waf_path)
|
||||
content = content.replace('{$WAF_ROOT}', waf_root)
|
||||
return content
|
||||
|
||||
|
||||
def autoMakeLuaConfSingle(file):
|
||||
path = getServerDir() + "/waf/rule/" + file + ".json"
|
||||
to_path = getServerDir() + "/waf/conf/rule_" + file + ".lua"
|
||||
content = mw.readFile(path)
|
||||
# print(content)
|
||||
content = json.loads(content)
|
||||
listToLuaFile(to_path, content)
|
||||
|
||||
|
||||
def autoMakeLuaImportSingle(file):
|
||||
path = getServerDir() + "/waf/" + file + ".json"
|
||||
to_path = getServerDir() + "/waf/conf/waf_" + file + ".lua"
|
||||
content = mw.readFile(path)
|
||||
# print(content)
|
||||
content = json.loads(content)
|
||||
listToLuaFile(to_path, content)
|
||||
|
||||
|
||||
def autoMakeLuaHtmlSingle(file):
|
||||
path = getServerDir() + "/waf/html/" + file + ".html"
|
||||
to_path = getServerDir() + "/waf/html/html_" + file + ".lua"
|
||||
content = mw.readFile(path)
|
||||
htmlToLuaFile(to_path, content)
|
||||
|
||||
|
||||
def autoMakeLuaConf():
|
||||
conf_list = ['args', 'cookie', 'ip_black', 'ip_white',
|
||||
'ipv6_black', 'post', 'scan_black', 'url',
|
||||
'user_agent']
|
||||
for x in conf_list:
|
||||
autoMakeLuaConfSingle(x)
|
||||
|
||||
import_list = ['config', 'site', 'domains']
|
||||
for x in import_list:
|
||||
autoMakeLuaImportSingle(x)
|
||||
|
||||
html_list = ['get', 'post', 'safe_js', 'user_agent', 'cookie', 'other']
|
||||
for x in html_list:
|
||||
autoMakeLuaHtmlSingle(x)
|
||||
|
||||
|
||||
def initDefaultInfo():
|
||||
path = getServerDir()
|
||||
djson = path + "/waf/domains.json"
|
||||
default_json = path + "/waf/default.json"
|
||||
if os.path.exists(djson):
|
||||
content = mw.readFile(djson)
|
||||
content = json.loads(content)
|
||||
|
||||
ddata = {}
|
||||
dlist = []
|
||||
for i in content:
|
||||
dlist.append(i["name"])
|
||||
|
||||
dlist.append('unset')
|
||||
ddata["list"] = dlist
|
||||
if len(ddata["list"]) < 1:
|
||||
ddata["default"] = "unset"
|
||||
else:
|
||||
ddata["default"] = dlist[0]
|
||||
|
||||
mw.writeFile(default_json, json.dumps(ddata))
|
||||
|
||||
|
||||
def autoMakeConfig():
|
||||
path = getServerDir()
|
||||
|
||||
initDomainInfo()
|
||||
initSiteInfo()
|
||||
initTotalInfo()
|
||||
autoMakeLuaConf()
|
||||
|
||||
|
||||
def restartWeb():
|
||||
autoMakeConfig()
|
||||
mw.restartWeb()
|
||||
|
||||
|
||||
def initDreplace():
|
||||
|
||||
path = getServerDir()
|
||||
if not os.path.exists(path + '/waf'):
|
||||
if not os.path.exists(path + '/waf/lua'):
|
||||
sdir = getPluginDir() + '/waf'
|
||||
cmd = 'cp -rf ' + sdir + ' ' + path
|
||||
mw.execShell(cmd)
|
||||
|
||||
logs_path = path + '/logs'
|
||||
if not os.path.exists(logs_path):
|
||||
mw.execShell('mkdir -p ' + logs_path)
|
||||
|
||||
debug_log = path + '/debug.log'
|
||||
if not os.path.exists(debug_log):
|
||||
mw.execShell('echo "" > ' + debug_log)
|
||||
|
||||
config = path + '/waf/config.json'
|
||||
content = mw.readFile(config)
|
||||
content = json.loads(content)
|
||||
@@ -214,6 +359,16 @@ def initDreplace():
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(config, content)
|
||||
|
||||
config_common = path + "/waf/lua/common.lua"
|
||||
content = mw.readFile(config_common)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(config_common, content)
|
||||
|
||||
init_worker = path + "/waf/lua/init_worker.lua"
|
||||
content = mw.readFile(init_worker)
|
||||
content = contentReplace(content)
|
||||
mw.writeFile(init_worker, content)
|
||||
|
||||
waf_conf = mw.getServerDir() + "/openresty/nginx/conf/luawaf.conf"
|
||||
waf_tpl = getPluginDir() + "/conf/luawaf.conf"
|
||||
content = mw.readFile(waf_tpl)
|
||||
@@ -223,6 +378,13 @@ def initDreplace():
|
||||
initDomainInfo()
|
||||
initSiteInfo()
|
||||
initTotalInfo()
|
||||
autoMakeLuaConf()
|
||||
initDefaultInfo()
|
||||
|
||||
pSqliteDb()
|
||||
|
||||
if not mw.isAppleSystem():
|
||||
mw.execShell("chown -R www:www " + path)
|
||||
|
||||
|
||||
def start():
|
||||
@@ -233,6 +395,9 @@ def start():
|
||||
conf = conf.replace('#include luawaf.conf;', "include luawaf.conf;")
|
||||
mw.writeFile(path, conf)
|
||||
|
||||
import tool_task
|
||||
tool_task.createBgTask()
|
||||
|
||||
mw.restartWeb()
|
||||
return 'ok'
|
||||
|
||||
@@ -243,6 +408,10 @@ def stop():
|
||||
conf = conf.replace('include luawaf.conf;', "#include luawaf.conf;")
|
||||
|
||||
mw.writeFile(path, conf)
|
||||
|
||||
import tool_task
|
||||
tool_task.removeBgTask()
|
||||
|
||||
mw.restartWeb()
|
||||
return 'ok'
|
||||
|
||||
@@ -254,8 +423,10 @@ def restart():
|
||||
|
||||
def reload():
|
||||
stop()
|
||||
mw.execShell('rm -rf ' + mw.getServerDir() +
|
||||
"/openresty/nginx/logs/error.log")
|
||||
|
||||
errlog = mw.getServerDir() + "/openresty/nginx/logs/error.log"
|
||||
mw.execShell('rm -rf ' + errlog)
|
||||
|
||||
start()
|
||||
return 'ok'
|
||||
|
||||
@@ -306,7 +477,7 @@ def addRule():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(fpath, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!', content)
|
||||
|
||||
|
||||
@@ -328,7 +499,7 @@ def removeRule():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(fpath, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!', content)
|
||||
|
||||
|
||||
@@ -353,7 +524,7 @@ def setRuleState():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(fpath, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!', content)
|
||||
|
||||
|
||||
@@ -384,7 +555,7 @@ def modifyRule():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(fpath, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!', content)
|
||||
|
||||
|
||||
@@ -425,6 +596,7 @@ def addSiteRule():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -460,6 +632,7 @@ def addIpWhite():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -480,6 +653,8 @@ def removeIpWhite():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -515,6 +690,8 @@ def addIpBlack():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -535,6 +712,8 @@ def removeIpBlack():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -553,6 +732,7 @@ def setIpv6Black():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -569,9 +749,10 @@ def delIpv6Black():
|
||||
content = json.loads(content)
|
||||
|
||||
content.remove(addr)
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -594,6 +775,8 @@ def removeSiteRule():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -608,11 +791,13 @@ def setObjStatus():
|
||||
cobj = json.loads(content)
|
||||
|
||||
o = args['obj']
|
||||
status = args['statusCode']
|
||||
status = int(args['statusCode'])
|
||||
cobj[o]['status'] = status
|
||||
|
||||
cjson = mw.getJson(cobj)
|
||||
mw.writeFile(conf, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -632,6 +817,32 @@ def setRetry():
|
||||
cjson = mw.getJson(cobj)
|
||||
mw.writeFile(conf, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!', [])
|
||||
|
||||
|
||||
def setSafeVerify():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['auto', 'time', 'cpu'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
conf = getJsonPath('config')
|
||||
content = mw.readFile(conf)
|
||||
cobj = json.loads(content)
|
||||
|
||||
cobj['safe_verify']['time'] = args['time']
|
||||
cobj['safe_verify']['cpu'] = args['cpu']
|
||||
|
||||
if args['auto'] == '0':
|
||||
cobj['safe_verify']['auto'] = False
|
||||
else:
|
||||
cobj['safe_verify']['auto'] = True
|
||||
|
||||
cjson = mw.getJson(cobj)
|
||||
mw.writeFile(conf, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!', [])
|
||||
|
||||
|
||||
@@ -642,7 +853,7 @@ def setSiteRetry():
|
||||
def setCcConf():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['siteName', 'cycle', 'limit',
|
||||
'endtime', 'is_open_global', 'increase'])
|
||||
'endtime', 'is_open_global'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
@@ -661,6 +872,8 @@ def setCcConf():
|
||||
|
||||
cjson = mw.getJson(cobj)
|
||||
mw.writeFile(conf, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!', [])
|
||||
|
||||
|
||||
@@ -677,6 +890,8 @@ def saveScanRule():
|
||||
path = getRuleJsonPath('scan_black')
|
||||
cjson = mw.getJson(args)
|
||||
mw.writeFile(path, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!', [])
|
||||
|
||||
|
||||
@@ -716,6 +931,26 @@ def getSiteConfig():
|
||||
return mw.returnJson(True, 'ok!', content)
|
||||
|
||||
|
||||
def getSiteListData():
|
||||
path = getServerDir() + "/waf/default.json"
|
||||
data = mw.readFile(path)
|
||||
return json.loads(data)
|
||||
|
||||
|
||||
def setDefaultSite(name):
|
||||
path = getServerDir() + "/waf/default.json"
|
||||
data = mw.readFile(path)
|
||||
data = json.loads(data)
|
||||
data['default'] = name
|
||||
mw.writeFile(path, json.dumps(data))
|
||||
return mw.returnJson(True, 'OK')
|
||||
|
||||
|
||||
def getDefaultSite():
|
||||
data = getSiteListData()
|
||||
return mw.returnJson(True, 'OK', data)
|
||||
|
||||
|
||||
def getSiteConfigByName():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['siteName'])
|
||||
@@ -749,6 +984,8 @@ def addSiteCdnHeader():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '添加成功!')
|
||||
|
||||
|
||||
@@ -768,6 +1005,8 @@ def removeSiteCdnHeader():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '删除成功!')
|
||||
|
||||
|
||||
@@ -790,29 +1029,44 @@ def importData():
|
||||
|
||||
path = getRuleJsonPath(args['s_Name'])
|
||||
mw.writeFile(path, args['pdata'])
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def getLogsList():
|
||||
args = getArgs()
|
||||
data = checkArgs(args, ['siteName'])
|
||||
data = checkArgs(args, ['site', 'page', 'page_size', 'tojs'])
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
data = []
|
||||
path = mw.getLogsDir() + '/waf'
|
||||
page = int(args['page'])
|
||||
page_size = int(args['page_size'])
|
||||
domain = args['site']
|
||||
tojs = args['tojs']
|
||||
|
||||
if not os.path.exists(path):
|
||||
return mw.returnJson(False, '还未生成!', [])
|
||||
conn = pSqliteDb('logs')
|
||||
|
||||
files = os.listdir(path)
|
||||
for f in files:
|
||||
if f == '.DS_Store':
|
||||
continue
|
||||
f = f.split('_')
|
||||
if f[0] == args['siteName']:
|
||||
fl = f[1].split('.')
|
||||
data.append(fl[0])
|
||||
field = 'time,ip,domain,server_name,method,uri,user_agent,rule_name,reason'
|
||||
limit = str(page_size) + ' offset ' + str(page_size * (page - 1))
|
||||
|
||||
condition = ''
|
||||
conn = conn.field(field)
|
||||
conn = conn.where("1=1", ()).where("domain=?", (domain,))
|
||||
|
||||
clist = conn.limit(limit).order('time desc').inquiry()
|
||||
count_key = "count(*) as num"
|
||||
count = conn.field(count_key).limit('').order('').inquiry()
|
||||
# print(count)
|
||||
count = count[0][count_key]
|
||||
|
||||
data = {}
|
||||
_page = {}
|
||||
_page['count'] = count
|
||||
_page['p'] = page
|
||||
_page['row'] = page_size
|
||||
_page['tojs'] = tojs
|
||||
data['page'] = mw.getPage(_page)
|
||||
data['data'] = clist
|
||||
|
||||
return mw.returnJson(True, 'ok!', data)
|
||||
|
||||
@@ -823,7 +1077,7 @@ def getSafeLogs():
|
||||
if not data[0]:
|
||||
return data[1]
|
||||
|
||||
path = mw.getLogsDir() + '/waf'
|
||||
path = getServerDir() + '/logs'
|
||||
file = path + '/' + args['siteName'] + '_' + args['toDate'] + '.log'
|
||||
if not os.path.exists(file):
|
||||
return mw.returnJson(False, "文件不存在!")
|
||||
@@ -859,6 +1113,7 @@ def setObjOpen():
|
||||
|
||||
cjson = mw.getJson(cobj)
|
||||
mw.writeFile(conf, cjson)
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -888,6 +1143,7 @@ def setSiteObjOpen():
|
||||
|
||||
cjson = mw.getJson(content)
|
||||
mw.writeFile(path, cjson)
|
||||
restartWeb()
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
@@ -908,6 +1164,12 @@ def installPreInspection():
|
||||
return 'ok'
|
||||
|
||||
|
||||
def cleanDropIp():
|
||||
url = "http://127.0.0.1/clean_waf_drop_ip"
|
||||
data = mw.httpGet(url)
|
||||
return mw.returnJson(True, 'ok!', data)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
if func == 'status':
|
||||
@@ -964,12 +1226,16 @@ if __name__ == "__main__":
|
||||
print(setSiteCcConf())
|
||||
elif func == 'set_retry':
|
||||
print(setRetry())
|
||||
elif func == 'set_safe_verify':
|
||||
print(setSafeVerify())
|
||||
elif func == 'set_site_retry':
|
||||
print(setSiteRetry())
|
||||
elif func == 'save_scan_rule':
|
||||
print(saveScanRule())
|
||||
elif func == 'get_site_config':
|
||||
print(getSiteConfig())
|
||||
elif func == 'get_default_site':
|
||||
print(getDefaultSite())
|
||||
elif func == 'get_site_config_byname':
|
||||
print(getSiteConfigByName())
|
||||
elif func == 'add_site_cdn_header':
|
||||
@@ -990,5 +1256,7 @@ if __name__ == "__main__":
|
||||
print(getWafConf())
|
||||
elif func == 'waf_site':
|
||||
print(getWafSite())
|
||||
elif func == 'clean_drop_ip':
|
||||
print(cleanDropIp())
|
||||
else:
|
||||
print('error')
|
||||
|
||||
@@ -11,5 +11,5 @@
|
||||
"home":"https://github.com/loveshell/ngx_lua_waf",
|
||||
"date":"2019-04-21",
|
||||
"pid": "1",
|
||||
"versions": ["0.1"]
|
||||
"versions": ["0.2.2"]
|
||||
}
|
||||
@@ -7,31 +7,99 @@ rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
serverPath=$(dirname "$rootPath")
|
||||
|
||||
|
||||
install_tmp=${rootPath}/tmp/mw_install.pl
|
||||
|
||||
action=$1
|
||||
version=$2
|
||||
sys_os=`uname`
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
if [ "$sys_os" == "Darwin" ];then
|
||||
BAK='_bak'
|
||||
else
|
||||
BAK=''
|
||||
fi
|
||||
|
||||
|
||||
Install_of(){
|
||||
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
mkdir -p $serverPath/source/op_waf
|
||||
mkdir -p $serverPath/op_waf
|
||||
|
||||
echo '0.1' > $serverPath/op_waf/version.pl
|
||||
# luarocks
|
||||
if [ ! -f $serverPath/source/op_waf/luarocks-3.5.0.tar.gz ];then
|
||||
wget --no-check-certificate -O $serverPath/source/op_waf/luarocks-3.5.0.tar.gz http://luarocks.org/releases/luarocks-3.5.0.tar.gz
|
||||
fi
|
||||
|
||||
# which luarocks
|
||||
# if [ "$?" != "0" ];then
|
||||
if [ ! -d $serverPath/op_waf/luarocks ];then
|
||||
cd $serverPath/source/op_waf && tar xvf luarocks-3.5.0.tar.gz
|
||||
# cd luarocks-3.9.1 && ./configure && make bootstrap
|
||||
|
||||
cd luarocks-3.5.0 && ./configure --prefix=$serverPath/op_waf/luarocks --with-lua-include=$serverPath/openresty/luajit/include/luajit-2.1 --with-lua-bin=$serverPath/openresty/luajit/bin
|
||||
make -I${serverPath}/openresty/luajit/bin
|
||||
make install
|
||||
fi
|
||||
|
||||
|
||||
if [ ! -f $serverPath/source/op_waf/lsqlite3_fsl09y.zip ];then
|
||||
wget --no-check-certificate -O $serverPath/source/op_waf/lsqlite3_fsl09y.zip http://lua.sqlite.org/index.cgi/zip/lsqlite3_fsl09y.zip?uuid=fsl_9y
|
||||
cd $serverPath/source/op_waf && unzip lsqlite3_fsl09y.zip
|
||||
fi
|
||||
|
||||
if [ ! -d $serverPath/source/op_waf/lsqlite3_fsl09y ];then
|
||||
cd $serverPath/source/op_waf && unzip lsqlite3_fsl09y.zip
|
||||
fi
|
||||
|
||||
PATH=${serverPath}/openresty/luajit:${serverPath}/openresty/luajit/include/luajit-2.1:$PATH
|
||||
export PATH=$PATH:$serverPath/op_waf/luarocks/bin
|
||||
|
||||
if [ ! -f $serverPath/op_waf/waf/conf/lsqlite3.so ];then
|
||||
if [ "${sys_os}" == "Darwin" ];then
|
||||
cd $serverPath/source/op_waf/lsqlite3_fsl09y
|
||||
find_cfg=`cat Makefile | grep 'SQLITE_DIR'`
|
||||
if [ "$find_cfg" == "" ];then
|
||||
LIB_SQLITE_DIR=`brew info sqlite | grep /usr/local/Cellar/sqlite | cut -d \ -f 1 | awk 'END {print}'`
|
||||
echo $LIB_SQLITE_DIR
|
||||
sed -i $BAK "s#\$(ROCKSPEC)#\$(ROCKSPEC) SQLITE_DIR=${LIB_SQLITE_DIR}#g" Makefile
|
||||
fi
|
||||
make
|
||||
else
|
||||
cd $serverPath/source/op_waf/lsqlite3_fsl09y && make
|
||||
fi
|
||||
fi
|
||||
|
||||
# copy to code path
|
||||
DEFAULT_DIR=$serverPath/op_waf/luarocks/lib/lua/5.1
|
||||
if [ -f ${DEFAULT_DIR}/lsqlite3.so ];then
|
||||
mkdir -p $serverPath/op_waf/waf/conf
|
||||
cp -rf ${DEFAULT_DIR}/lsqlite3.so $serverPath/op_waf/waf/conf/lsqlite3.so
|
||||
fi
|
||||
|
||||
echo "${version}" > $serverPath/op_waf/version.pl
|
||||
echo 'install ok' > $install_tmp
|
||||
|
||||
cd ${rootPath} && python3 plugins/op_waf/index.py start
|
||||
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py start
|
||||
|
||||
|
||||
|
||||
# cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py restart
|
||||
}
|
||||
|
||||
Uninstall_of(){
|
||||
|
||||
cd ${rootPath} && python3 plugins/op_waf/index.py stop
|
||||
rm -rf $serverPath/op_waf
|
||||
cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py stop
|
||||
if [ "$?" == "0" ];then
|
||||
rm -rf $serverPath/op_waf
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
action=$1
|
||||
type=$2
|
||||
|
||||
action=$1
|
||||
if [ "${1}" == 'install' ];then
|
||||
Install_of
|
||||
|
||||
+311
-211
@@ -28,7 +28,7 @@ function setRequestCode(ruleName, statusCode){
|
||||
title: "设置响应代码【" + ruleName + "】",
|
||||
area: '300px',
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: true,
|
||||
content: '<div class="bt-form pd20 pb70">\
|
||||
<div class="line">\
|
||||
@@ -69,8 +69,10 @@ function setObjOpen(ruleName){
|
||||
owPost('set_obj_open', {obj:ruleName},function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
if (rdata.status){
|
||||
layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
wafGloabl();
|
||||
|
||||
showMsg(rdata.msg, function(){
|
||||
wafGloabl();
|
||||
},{icon:1,time:2000,shade: [0.3, '#000']},2000);
|
||||
} else {
|
||||
layer.msg('设置失败!',{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
@@ -84,7 +86,7 @@ function saveCcRule(siteName,is_open_global, type) {
|
||||
if(type == 2){
|
||||
// set_aicc_open('start');
|
||||
increase = "0";
|
||||
}else{
|
||||
} else {
|
||||
// set_aicc_open('stop');
|
||||
increase = type;
|
||||
}
|
||||
@@ -144,7 +146,7 @@ function setCcRule(cycle, limit, endtime, siteName, increase){
|
||||
type: 1,
|
||||
title: "设置CC规则",
|
||||
area: '540px',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<form class="bt-form pd20 pb70">\
|
||||
<div class="line">\
|
||||
@@ -164,7 +166,10 @@ function setCcRule(cycle, limit, endtime, siteName, increase){
|
||||
<li>请不要设置过于严格的CC规则,以免影响正常用户体验</li>\
|
||||
<li><font style="color:red;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用:全局设置当前CC规则,且覆盖当前全部站点的CC规则</font></li>\
|
||||
</ul>\
|
||||
<div class="bt-form-submit-btn"><button type="button" class="btn btn-danger btn-sm btn_cc_all" style="margin-right:10px;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用</button><button type="button" class="btn btn-success btn-sm btn_cc_present">应用</button></div>\
|
||||
<div class="bt-form-submit-btn">\
|
||||
<button type="button" class="btn btn-danger btn-sm btn_cc_all" style="margin-right:10px;display:'+ (siteName == 'undefined'?'display: inline-block;':'none') +';">全局应用</button>\
|
||||
<button type="button" class="btn btn-success btn-sm btn_cc_present">应用</button>\
|
||||
</div>\
|
||||
</form>',
|
||||
success:function(layero,index){
|
||||
$('.btn_cc_all').click(function(){
|
||||
@@ -184,7 +189,7 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
|
||||
type: 1,
|
||||
title: "设置恶意容忍规则",
|
||||
area: '500px',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<form class="bt-form pd20 pb70">\
|
||||
<div class="line">\
|
||||
@@ -201,9 +206,12 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
|
||||
</div>\
|
||||
<ul class="help-info-text c7 ptb10">\
|
||||
<li><font style="color:red;">'+ retry_cycle + '</font> 秒内累计恶意请求超过 <font style="color:red;">' + retry + '</font> 次,封锁 <font style="color:red;">' + retry_time + '</font> 秒</li>\
|
||||
<li><font style="color:red;">全局应用:全局设置当前恶意容忍规则,且覆盖当前全部站点的恶意容忍规则</li>\
|
||||
<li><font style="color:red;">全局应用:全局设置当前恶意容忍规则,且覆盖当前全部站点的恶意容忍规则</font></li>\
|
||||
</ul>\
|
||||
<div class="bt-form-submit-btn"><button type="button" class="btn btn-danger btn-sm btn_retry_all" style="margin-right:10px;display:'+ (siteName == undefined?'inline-block;':'none') +';">全局应用</button><button type="button" class="btn btn-success btn-sm btn_retry_present">应用</button></div>\
|
||||
<div class="bt-form-submit-btn">\
|
||||
<button type="button" class="btn btn-danger btn-sm btn_retry_all" style="margin-right:10px;display:'+ (siteName == undefined?'inline-block;':'none') +';">全局应用</button>\
|
||||
<button type="button" class="btn btn-success btn-sm btn_retry_present">应用</button>\
|
||||
</div>\
|
||||
</form>',
|
||||
success:function(){
|
||||
$('.btn_retry_all').click(function(){
|
||||
@@ -217,6 +225,65 @@ function setRetry(retry_cycle, retry, retry_time, siteName) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
//设置safe_verify规则
|
||||
function setSafeVerify(auto, cpu, time, siteName) {
|
||||
var svlayer = layer.open({
|
||||
type: 1,
|
||||
title: "设置强制安全验证",
|
||||
area: '500px',
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<form class="bt-form pd20 pb70">\
|
||||
<div class="line">\
|
||||
<span class="tname">CPU</span>\
|
||||
<div class="info-r"><input class="bt-input-text" name="cpu" type="number" max-number="100" value="'+ cpu + '" /> %</div>\
|
||||
</div>\
|
||||
<div class="line">\
|
||||
<span class="tname">通行时间</span>\
|
||||
<div class="info-r"><input class="bt-input-text" name="time" type="number" value="'+ time + '" /> 秒</div>\
|
||||
</div>\
|
||||
<div class="line">\
|
||||
<span class="tname">开启自动</span>\
|
||||
<div class="info-r">\
|
||||
<select class="bt-input-text mr5" style="width:80px" name="auto">\
|
||||
<option value="0" '+(auto==false?"selected=selected":"")+'>关闭</option>\
|
||||
<option value="1" '+(auto==true?"selected=selected":"")+'>开启</option>\
|
||||
</select>\
|
||||
</div>\
|
||||
</div>\
|
||||
<ul class="help-info-text c7 ptb10">\
|
||||
<li><font style="color:red;">全局设置强制安全验证</font></li>\
|
||||
<li>开启自动后:cpu超过['+cpu+'%]后,强制验证。</li>\
|
||||
</ul>\
|
||||
<div class="bt-form-submit-btn">\
|
||||
<button type="button" class="btn btn-success btn-sm btn_sv_present">应用</button>\
|
||||
</div>\
|
||||
</form>',
|
||||
success:function(index){
|
||||
$('.btn_sv_present').click(function(){
|
||||
var pdata = {
|
||||
siteName: siteName,
|
||||
cpu: $("input[name='cpu']").val(),
|
||||
auto: $("select[name='auto']").val(),
|
||||
time: $("input[name='time']").val(),
|
||||
}
|
||||
var act = 'set_safe_verify';
|
||||
owPost(act, pdata, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
showMsg(rdata.msg, function() {
|
||||
layer.close(svlayer);
|
||||
wafGloabl();
|
||||
},{ icon: rdata.status ? 1 : 2 },1000);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//保存retry规则
|
||||
function saveRetry(siteName,type) {
|
||||
var pdata = {
|
||||
@@ -253,15 +320,6 @@ function addRule(ruleName) {
|
||||
},1000);
|
||||
}
|
||||
});
|
||||
|
||||
// var loadT = layer.msg('正在添加,请稍候..', { icon: 16, time: 0 });
|
||||
// $.post('/plugin?action=a&name=btwaf&s=add_rule', pdata, function (rdata) {
|
||||
// layer.close(loadT);
|
||||
// layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
// if (rdata.status) {
|
||||
// set_obj_conf(ruleName, 1);
|
||||
// }
|
||||
// });
|
||||
}
|
||||
|
||||
function modifyRule(index, ruleName) {
|
||||
@@ -339,7 +397,7 @@ function setObjConf(ruleName, type) {
|
||||
type: 1,
|
||||
title: "编辑规则【" + ruleName + "】",
|
||||
area: ['700px', '530px'],
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15">\
|
||||
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
|
||||
@@ -405,7 +463,7 @@ function scanRule() {
|
||||
type: 1,
|
||||
title: "常用扫描器过滤规则",
|
||||
area: '650px',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<form class="bt-form pd20 pb70">\
|
||||
<div class="line">\
|
||||
@@ -571,7 +629,7 @@ function ipWhite(type) {
|
||||
type: 1,
|
||||
title: "管理IP白名单",
|
||||
area: ['500px', '500px'],
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15 ipv4_list">\
|
||||
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
|
||||
@@ -695,6 +753,23 @@ function addIpBlack() {
|
||||
});
|
||||
}
|
||||
|
||||
function addIpBlackArgs(ip) {
|
||||
var pdata = {
|
||||
start_ip: ip,
|
||||
end_ip: ip,
|
||||
}
|
||||
|
||||
if (pdata['start_ip'].split('.').length < 4 || pdata['end_ip'].split('.').length < 4) {
|
||||
layer.msg('起始IP或结束IP格式不正确!');
|
||||
return;
|
||||
}
|
||||
|
||||
owPost('add_ip_black', pdata, function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//从IP黑名单删除IP段
|
||||
function removeIpBlack(index) {
|
||||
@@ -714,7 +789,7 @@ function ipBlack(type) {
|
||||
type: 1,
|
||||
title: "管理IP黑名单",
|
||||
area: ['500px', '500px'],
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="tab_list"><div class="tab_block active">IPv4黑名单</div><div class="tab_block">IPv6黑名单</div></div>\
|
||||
<div class="pd15 ipv4_block">\
|
||||
@@ -820,17 +895,17 @@ function wafScreen(){
|
||||
|
||||
con += '<div class="screen">\
|
||||
<div class="line"><span class="name">POST渗透</span><span class="val">'+rdata.rules.post+'</span></div>\
|
||||
<div class="line"><span class="name">GET渗透</span><span class="val">0</span></div>\
|
||||
<div class="line"><span class="name">GET渗透</span><span class="val">'+rdata.rules.args+'</span></div>\
|
||||
<div class="line"><span class="name">CC攻击</span><span class="val">'+rdata.rules.cc+'</span></div>\
|
||||
<div class="line"><span class="name">恶意User-Agent</span><span class="val">'+rdata.rules.user_agent+'</span></div>\
|
||||
<div class="line"><span class="name">Cookie渗透</span><span class="val">'+rdata.rules.cookie+'</span></div>\
|
||||
<div class="line"><span class="name">恶意扫描</span><span class="val">0</span></div>\
|
||||
<div class="line"><span class="name">恶意扫描</span><span class="val">'+rdata.rules.scan+'</span></div>\
|
||||
<div class="line"><span class="name">恶意HEAD请求</span><span class="val">0</span></div>\
|
||||
<div class="line"><span class="name">URI自定义拦截</span><span class="val">0</span></div>\
|
||||
<div class="line"><span class="name">URI保护</span><span class="val">0</span></div>\
|
||||
<div class="line"><span class="name">恶意文件上传</span><span class="val">0</span></div>\
|
||||
<div class="line"><span class="name">禁止的扩展名</span><span class="val">0</span></div>\
|
||||
<div class="line"><span class="name">禁止PHP脚本</span><span class="val">0</span></div>\
|
||||
<div class="line"><span class="name">URI自定义拦截</span><span class="val">'+rdata.rules.url+'</span></div>\
|
||||
<div class="line"><span class="name">URI保护</span><span class="val">'+rdata.rules.args+'</span></div>\
|
||||
<div class="line"><span class="name">恶意文件上传</span><span class="val">'+rdata.rules.upload_ext+'</span></div>\
|
||||
<div class="line"><span class="name">禁止的扩展名</span><span class="val">'+rdata.rules.path+'</span></div>\
|
||||
<div class="line"><span class="name">禁止PHP脚本</span><span class="val">'+rdata.rules.php_path+'</span></div>\
|
||||
</div>';
|
||||
|
||||
con += '<div style="width:660px;"><ul class="help-info-text c7">\
|
||||
@@ -878,6 +953,16 @@ function wafGloabl(){
|
||||
<td style="text-align: center;">--</td>\
|
||||
<td class="text-right"><a class="btlink" onclick="setRetry('+ rdata.retry.retry_cycle + ',' + rdata.retry.retry + ',' + rdata.retry.retry_time + ')">初始规则</a></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td>强制安全验证</td>\
|
||||
<td>'+rdata.safe_verify.ps+'</td>\
|
||||
<td>--</td>\
|
||||
<td style="text-align: center;"><div class="ssh-item">\
|
||||
<input class="btswitch btswitch-ios" id="close_safe_verify" type="checkbox" '+(rdata.safe_verify.open ? 'checked' : '')+'>\
|
||||
<label class="btswitch-btn" for="close_safe_verify" onclick="setObjOpen(\'safe_verify\')"></label></div>\
|
||||
</td>\
|
||||
<td class="text-right"><a class="btlink" onclick="setSafeVerify('+ rdata.safe_verify.auto + ',' + rdata.safe_verify.cpu + ',' + rdata.safe_verify.time + ')">设置</a> | <a class="btlink" href="javascript:;" onclick="onlineEditFile(0,\''+rdata['reqfile_path']+'/safe_js.html\')">响应内容</a></td>\
|
||||
</tr>\
|
||||
<tr>\
|
||||
<td>GET-URI过滤</td>\
|
||||
<td>'+ rdata.get.ps + '</td>\
|
||||
@@ -956,146 +1041,6 @@ function back_css(v) {
|
||||
}
|
||||
}
|
||||
|
||||
//查看网站日志
|
||||
function siteWafLog(siteName) {
|
||||
var loadT = layer.msg('正在处理,请稍候..', { icon: 16, time: 0 });
|
||||
owPost('get_logs_list', { siteName: siteName } , function (data) {
|
||||
var tmp = $.parseJSON(data.data);
|
||||
var rdata = tmp.data;
|
||||
var selectLogDay = "";
|
||||
var day = rdata[0];
|
||||
for (var i = 0; i < rdata.length; i++) {
|
||||
selectLogDay += '<option value="' + rdata[i] + '">' + rdata[i] + '</option>';
|
||||
}
|
||||
if (rdata == "") {
|
||||
layer.msg("暂无日志记录", { icon: 6, shade: 0.3, time: 1000 });
|
||||
return
|
||||
}
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "日志【" + siteName + "】",
|
||||
area: ['880px', '500px'],
|
||||
closeBtn: 2,
|
||||
shadeClose: false,
|
||||
content: '<div class="lib-box pd15 lib-box-log">\
|
||||
<div class="lib-con-title" style="height:40px"><select id="selectLogDay" class="bt-input-text" onchange="siteLogCon(\''+ siteName + '\',this.options[this.options.selectedIndex].value,1)">' + selectLogDay + '</select></div>\
|
||||
<div class="lib-con">\
|
||||
<div class="divtable">\
|
||||
<div id="site_waf_log" style="max-height:400px;overflow:auto;border:#ddd 1px solid">\
|
||||
<table class="table table-hover" style="border:none;">\
|
||||
<thead><tr><th width="150">时间</th><th width="120">用户IP</th><th width="70">类型</th><th>URI地址</th><th class="tdhide">User-Agent</th><th width="60">状态</th><th width="100">过滤器</th><th class="tdhide">过滤规则</th><th width="100" class="text-right">操作</th></tr></thead>\
|
||||
<tbody id="LogDayCon"></tbody>\
|
||||
</table>\
|
||||
</div>\
|
||||
</div>\
|
||||
<div class="page pull-right" id="size_log_page" style="margin-top:10px"></div>\
|
||||
</div>\
|
||||
</div>'
|
||||
});
|
||||
siteLogCon(siteName, day, 1);
|
||||
tableFixed("site_waf_log");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//日志内容
|
||||
function siteLogCon(siteName, day, page) {
|
||||
if (!page) page = 1;
|
||||
var last = page - 1;
|
||||
var next = page + 1;
|
||||
var pagehtml = '';
|
||||
$("#site_waf_log").scrollTop(0);
|
||||
|
||||
owPost('get_safe_logs', { siteName: siteName, toDate: day, p: page }, function(data){
|
||||
var tmp = $.parseJSON(data.data);
|
||||
if (!tmp.status){
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
return;
|
||||
}
|
||||
var rdata = tmp.data;
|
||||
var con = '';
|
||||
for (var i = 0; i < rdata.length; i++) {
|
||||
con += '<tr>\
|
||||
<td class="td0">'+ escapeHTML(rdata[i][0]) + '</td>\
|
||||
<td class="td1"><a class="btlink" href="javascript:add_log_ip_black(\''+ escapeHTML(rdata[i][1]) + '\');" title="加入黑名单">' + escapeHTML(rdata[i][1]) + '</a></td>\
|
||||
<td class="td2">'+ escapeHTML(rdata[i][2]) + '</td>\
|
||||
<td class="td3"><span class="td3txt">'+ escapeHTML(rdata[i][3]) + '</span></td>\
|
||||
<td class="tdhide td4">'+ escapeHTML(rdata[i][4]) + '</td><td>已拦截</td>\
|
||||
<td class="td5"><span class="filtertext">'+ escapeHTML(rdata[i][5]) + '</span></td>\
|
||||
<td class="tdhide td6">'+ escapeHTML(rdata[i][6]) + '</td>\
|
||||
<td class="text-right"><a href="javascript:;" class="btlink submit_msg" data-index="'+ i +'">误报</a> | <a href="javascript:;" class="btlink btwaf_details" data-index="'+ i +'">详细</a></td>\
|
||||
</tr>'
|
||||
}
|
||||
|
||||
$("#LogDayCon").html(con);
|
||||
pagehtml = '<a class="Pstart" onclick="site_log_con(\'' + siteName + '\',\'' + day + '\',1)">首页</a><a class="prevPage" onclick="site_log_con(\'' + siteName + '\',\'' + day + '\',' + last + ')">上一页</a><a class="nextPage" onclick="site_log_con(\'' + siteName + '\',\'' + day + '\',' + next + ')">下一页</a><a class="Pcount">第 ' + page + ' 页</a>';
|
||||
$("#size_log_page").html(pagehtml);
|
||||
if (rdata.length < 1) $(".nextPage").hide();
|
||||
if (last < 1) $(".prevPage").hide();
|
||||
|
||||
// 发送误报请求
|
||||
$(".submit_msg").click(function () {
|
||||
var _this = $(this);
|
||||
var res = rdata[$(this).attr('data-index')];
|
||||
layer.confirm('是否确定提交误报反馈?', { title: '误报反馈',closeBtn:2,icon:3}, function () {
|
||||
var url_address = res[3];
|
||||
var rule_arry = res[6].split(" >> ");
|
||||
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(" >> ");
|
||||
var incoming_value = '',risk_value = ''; //传入值,风险值
|
||||
if(rule_arry.length == 0) filter_rule = rule_arry[0]
|
||||
incoming_value = rule_arry[1] == undefined?'空':rule_arry[1];
|
||||
risk_value = incoming_value.match(new RegExp(rule_arry[0].replace(/\//g,'\\/'),'i'));
|
||||
risk_value = risk_value?risk_value[0]:'空';
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: time + "详情",
|
||||
area: '600px',
|
||||
closeBtn: 2,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15 lib-box">\
|
||||
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
|
||||
<tbody><tr><th>时间</th><td>'+ escapeHTML(time) + '</td><th>用户IP</th><td><a class="btlink" href="javascript:add_log_ip_black(\'' + escapeHTML(ip_address) + '\')" title="加入黑名单">' + escapeHTML(ip_address) + '</a></td></tr><tr><th>类型</th><td>' + escapeHTML(req_type) + '</td><th>过滤器</th><td>' + escapeHTML(filters) + '</td></tr></tbody></table>\
|
||||
<div><b style="margin-left:10px">URI地址</b></div>\
|
||||
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(url_address) + '</div></div>\
|
||||
<div><b style="margin-left:10px">User-Agent</b></div>\
|
||||
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(user_agent) + '</div></div>\
|
||||
<div><b style="margin-left:10px">过滤规则</b></div>\
|
||||
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(rule_arry[0]) + '</div></div>\
|
||||
<div><b style="margin-left:10px">传入值</b></div>\
|
||||
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(incoming_value) + '</div></div>\
|
||||
<div><b style="margin-left:10px">风险值</b></div>\
|
||||
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(risk_value) + '</div></div>\
|
||||
</div>'
|
||||
})
|
||||
})
|
||||
$("#LogDayCon td").click(function () {
|
||||
$(this).parents("tr").addClass("active").siblings().removeClass("active");
|
||||
});
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
function html_encode(value) {
|
||||
return $('<div></div>').html(value).text();
|
||||
}
|
||||
@@ -1190,7 +1135,7 @@ function siteRuleAdmin(siteName, ruleName, type) {
|
||||
type: 1,
|
||||
title: "管理网站过滤规则【" + title + "】",
|
||||
area: ['500px', '500px'],
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15">\
|
||||
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
|
||||
@@ -1237,7 +1182,7 @@ function cdnHeader(siteName, type) {
|
||||
type: 1,
|
||||
title: "管理网站【" + siteName + "】CDN-Headers",
|
||||
area: ['500px', '500px'],
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15">\
|
||||
<div style="border-bottom:#ccc 1px solid;margin-bottom:10px;padding-bottom:10px">\
|
||||
@@ -1342,7 +1287,7 @@ function setSiteObjConf(siteName, ruleName, type) {
|
||||
type: 1,
|
||||
title: "编辑网站【" + siteName + "】规则【" + ruleName + "】",
|
||||
area: ['700px', '530px'],
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15">\
|
||||
<div class="divtable">\
|
||||
@@ -1394,7 +1339,7 @@ function siteWafConfig(siteName, type) {
|
||||
type: 1,
|
||||
title: "网站配置【" + siteName + "】",
|
||||
area: ['700px', '500px'],
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div id="s_w_c"></div>'
|
||||
});
|
||||
@@ -1543,7 +1488,6 @@ function siteWafConfig(siteName, type) {
|
||||
|
||||
|
||||
function wafSite(){
|
||||
|
||||
owPost('get_site_config', {}, function(data){
|
||||
var tmp = $.parseJSON(data.data);
|
||||
var rdata = $.parseJSON(tmp.data);
|
||||
@@ -1553,32 +1497,20 @@ function wafSite(){
|
||||
i += 1;
|
||||
tbody += '<tr>\
|
||||
<td><a onclick="siteWafConfig(\''+ k + '\')" class="sitename btlink" title="' + k + '">' + k + '</a></td>\
|
||||
<td>\
|
||||
<input onclick="setSiteObjState(\''+ k + '\',\'get\')" type="checkbox" ' + (v.get ? 'checked' : '') + '><span class="' + back_css(v.total[1].value) + '" title="拦截GET渗透次数:' + v.total[1].value + '">' + v.total[1].value + '</span>\
|
||||
</td>\
|
||||
<td>\
|
||||
<input onclick="setSiteObjState(\''+ k + '\',\'post\')" type="checkbox" ' + (v.post ? 'checked' : '') + '><span class="' + back_css(v.total[0].value) + '" title="拦截POST渗透次数:' + v.total[0].value + '">' + v.total[0].value + '</span>\
|
||||
</td>\
|
||||
<td>\
|
||||
<input onclick="setSiteObjState(\''+ k + '\',\'user-agent\')" type="checkbox" ' + (v['user-agent'] ? 'checked' : '') + '><span class="' + back_css(v.total[3].value) + '" title="拦截恶意User-Agent次数:' + v.total[3].value + '">' + v.total[3].value + '</span>\
|
||||
</td>\
|
||||
<td>\
|
||||
<input onclick="setSiteObjState(\''+ k + '\',\'cookie\')" type="checkbox" ' + (v.cookie ? 'checked' : '') + '><span class="' + back_css(v.total[4].value) + '" title="拦截Cookie渗透次数:' + v.total[4].value + '">' + v.total[4].value + '</span>\
|
||||
</td>\
|
||||
<td>\
|
||||
<input onclick="setSiteObjState(\''+ k + '\',\'cdn\')" type="checkbox" ' + (v.cdn ? 'checked' : '') + '>\
|
||||
</td>\
|
||||
<td>\
|
||||
<input onclick="setSiteObjState(\''+ k + '\',\'cc\')" type="checkbox" ' + (v.cc.open ? 'checked' : '') + '><span class="' + back_css(v.total[2].value) + '" title="拦截CC攻击次数:' + v.total[2].value + '">' + v.total[2].value + '</span>\
|
||||
</td>\
|
||||
<td><input onclick="setSiteObjState(\''+ k + '\',\'get\')" type="checkbox" ' + (v.get ? 'checked' : '') + '><span class="' + back_css(v.total[1].value) + '" title="拦截GET渗透次数:' + v.total[1].value + '">' + v.total[1].value + '</span></td>\
|
||||
<td><input onclick="setSiteObjState(\''+ k + '\',\'post\')" type="checkbox" ' + (v.post ? 'checked' : '') + '><span class="' + back_css(v.total[0].value) + '" title="拦截POST渗透次数:' + v.total[0].value + '">' + v.total[0].value + '</span></td>\
|
||||
<td><input onclick="setSiteObjState(\''+ k + '\',\'user-agent\')" type="checkbox" ' + (v['user-agent'] ? 'checked' : '') + '><span class="' + back_css(v.total[3].value) + '" title="拦截恶意User-Agent次数:' + v.total[3].value + '">' + v.total[3].value + '</span></td>\
|
||||
<td><input onclick="setSiteObjState(\''+ k + '\',\'cookie\')" type="checkbox" ' + (v.cookie ? 'checked' : '') + '><span class="' + back_css(v.total[4].value) + '" title="拦截Cookie渗透次数:' + v.total[4].value + '">' + v.total[4].value + '</span></td>\
|
||||
<td><input onclick="setSiteObjState(\''+ k + '\',\'cdn\')" type="checkbox" ' + (v.cdn ? 'checked' : '') + '></td>\
|
||||
<td><input onclick="setSiteObjState(\''+ k + '\',\'cc\')" type="checkbox" ' + (v.cc.open ? 'checked' : '') + '><span class="' + back_css(v.total[2].value) + '" title="拦截CC攻击次数:' + v.total[2].value + '">' + v.total[2].value + '</span></td>\
|
||||
<td>\
|
||||
<div class="ssh-item" style="margin-left:0">\
|
||||
<input class="btswitch btswitch-ios" id="closeget_'+ i + '" type="checkbox" ' + (v.open ? 'checked' : '') + '>\
|
||||
<label class="btswitch-btn" for="closeget_'+ i + '" onclick="setSiteObjState(\'' + k + '\',\'open\')"></label>\
|
||||
</div>\
|
||||
</td>\
|
||||
<td class="text-right"><a onclick="siteWafLog(\''+ k + '\')" class="btlink ' + (v.log_size > 0 ? 'dot' : '') + '">日志</a> | <a onclick="siteWafConfig(\'' + k + '\')" class="btlink">设置</a></td>\
|
||||
</tr>'
|
||||
<td class="text-right"><a onclick="wafLogs(\''+ k + '\')" class="btlink ' + (v.log_size > 0 ? 'dot' : '') + '">日志</a> | <a onclick="siteWafConfig(\'' + k + '\')" class="btlink">设置</a></td>\
|
||||
</tr>';
|
||||
});
|
||||
|
||||
var con = '<div class="lib-box">\
|
||||
@@ -1612,27 +1544,195 @@ function wafSite(){
|
||||
|
||||
|
||||
|
||||
function wafHistory(){
|
||||
|
||||
function wafLogRequest(page){
|
||||
var args = {};
|
||||
args['page'] = page;
|
||||
args['page_size'] = 10;
|
||||
args['site'] = $('select[name="site"]').val();
|
||||
|
||||
var query_date = 'today';
|
||||
if ($('#time_choose').attr("data-name") != ''){
|
||||
query_date = $('#time_choose').attr("data-name");
|
||||
} else {
|
||||
query_date = $('#search_time button.cur').attr("data-name");
|
||||
}
|
||||
|
||||
args['query_date'] = query_date;
|
||||
args['tojs'] = 'wafLogRequest';
|
||||
|
||||
owPost('get_logs_list', args, function(rdata){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
var list = '';
|
||||
var data = rdata.data.data;
|
||||
if (data.length > 0){
|
||||
for(i in data){
|
||||
list += '<tr>';
|
||||
list += '<td><span class="overflow_hide" style="width:112px;">' + getLocalTime(data[i]['time'])+'</span></td>';
|
||||
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['domain'] +'</span></td>';
|
||||
list += '<td><span class="overflow_hide" style="width:60px;">' + data[i]['ip'] +'</span></td>';
|
||||
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['uri'] +'</span></td>';
|
||||
list += '<td><span class="overflow_hide" style="width:50px;">' + data[i]['rule_name'] +'</span></td>';
|
||||
list += '<td><span class="overflow_hide" style="width:200px;">' + data[i]['reason'] +'</span></td>';
|
||||
list += '<td><a data-id="'+i+'" href="javascript:;" class="btlink details" title="详情">详情</a></td>';
|
||||
list += '</tr>';
|
||||
}
|
||||
} else{
|
||||
list += '<tr><td colspan="8" style="text-align:center;">封锁日志为空</td></tr>';
|
||||
}
|
||||
|
||||
var table = '<div class="tablescroll">\
|
||||
<table id="DataBody" class="table table-hover" width="100%" cellspacing="0" cellpadding="0" border="0" style="border: 0 none;">\
|
||||
<thead><tr>\
|
||||
<th>时间</th>\
|
||||
<th>域名</th>\
|
||||
<th>IP</th>\
|
||||
<th>URI</th>\
|
||||
<th>规则名</th>\
|
||||
<th>原因</th>\
|
||||
<th style="text-align:right;">操作</th></tr></thead>\
|
||||
<tbody>\
|
||||
'+ list +'\
|
||||
</tbody></table>\
|
||||
</div>\
|
||||
<div id="wsPage" class="dataTables_paginate paging_bootstrap page"></div>';
|
||||
$('#ws_table').html(table);
|
||||
$('#wsPage').html(rdata.data.page);
|
||||
|
||||
$(".tablescroll .details").click(function(){
|
||||
var index = $(this).attr('data-id');
|
||||
var res = data[index];
|
||||
var ip = res.ip;
|
||||
var time = getLocalTime(res.time);
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: "【"+res.domain + "】详情",
|
||||
area: '600px',
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15 lib-box">\
|
||||
<table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
|
||||
<tbody><tr><th>时间</th><td>'+ time + '</td><th>用户IP</th><td><a class="btlink" href="javascript:addIpBlackArgs(\'' + escapeHTML(ip) + '\')" title="加入黑名单">' + escapeHTML(ip) + '</a></td></tr><tr><th>类型</th><td>' + escapeHTML(res.method) + '</td><th>过滤器</th><td>' + escapeHTML(res.rule_name) + '</td></tr></tbody></table>\
|
||||
<div><b style="margin-left:10px">URI地址</b></div>\
|
||||
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.uri) + '</div></div>\
|
||||
<div><b style="margin-left:10px">User-Agent</b></div>\
|
||||
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.user_agent) + '</div></div>\
|
||||
<div><b style="margin-left:10px">过滤规则</b></div>\
|
||||
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.rule_name) + '</div></div>\
|
||||
<div><b style="margin-left:10px">Reason</b></div>\
|
||||
<div class="lib-con pull-left mt10"><div class="divpre">'+ escapeHTML(res.reason) + '</div></div>\
|
||||
</div>'
|
||||
})
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function wafLogs(){
|
||||
var randstr = getRandomString(10);
|
||||
|
||||
|
||||
var html = '<div>\
|
||||
<div style="padding-bottom:10px;">\
|
||||
<span>网站: </span>\
|
||||
<select class="bt-input-text" name="site" style="margin-left:4px;width:100px;">\
|
||||
<option value="unset">未设置</option>\
|
||||
</select>\
|
||||
<span style="margin-left:10px">时间: </span>\
|
||||
<div class="input-group" style="margin-left:10px;width:350px;display: inline-table;vertical-align: top;">\
|
||||
<div id="search_time" class="input-group-btn btn-group-sm">\
|
||||
<button data-name="today" type="button" class="btn btn-default">今日</button>\
|
||||
<button data-name="yesterday" type="button" class="btn btn-default">昨日</button>\
|
||||
<button data-name="l7" type="button" class="btn btn-default">近7天</button>\
|
||||
<button data-name="l30" type="button" class="btn btn-default">近30天</button>\
|
||||
</div>\
|
||||
<span class="last-span"><input data-name="" type="text" id="time_choose" lay-key="1000001_'+randstr+'" class="form-control btn-group-sm" autocomplete="off" placeholder="自定义时间" style="display: inline-block;font-size: 12px;padding: 0 10px;height:30px;width: 200px;"></span>\
|
||||
</div>\
|
||||
<div style="float:right;"><button id="UncoverAll" class="btn btn-success btn-sm">解封所有</button></div>\
|
||||
</div>\
|
||||
<div class="divtable mtb10" id="ws_table"></div>\
|
||||
</div>';
|
||||
$(".soft-man-con").html(html);
|
||||
// wafLogRequest(1);
|
||||
|
||||
$("#UncoverAll").click(function(){
|
||||
owPost('clean_drop_ip',{},function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
var ndata = $.parseJSON(rdata.data);
|
||||
if (ndata.status == 0){
|
||||
layer.msg("解封所有成功",{icon:1,time:2000,shade: [0.3, '#000']});
|
||||
} else{
|
||||
layer.msg("解封所有异常:"+ndata.msg,{icon:5,time:2000,shade: [0.3, '#000']});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
//日期范围
|
||||
laydate.render({
|
||||
elem: '#time_choose',
|
||||
value:'',
|
||||
range:true,
|
||||
done:function(value, startDate, endDate){
|
||||
if(!value){
|
||||
return false;
|
||||
}
|
||||
|
||||
$('#search_time button').each(function(){
|
||||
$(this).removeClass('cur');
|
||||
});
|
||||
|
||||
var timeA = value.split('-');
|
||||
var start = $.trim(timeA[0]+'-'+timeA[1]+'-'+timeA[2])
|
||||
var end = $.trim(timeA[3]+'-'+timeA[4]+'-'+timeA[5])
|
||||
query_txt = toUnixTime(start + " 00:00:00") + "-"+ toUnixTime(end + " 00:00:00")
|
||||
|
||||
$('#time_choose').attr("data-name",query_txt);
|
||||
$('#time_choose').addClass("cur");
|
||||
|
||||
wafLogRequest(1);
|
||||
},
|
||||
});
|
||||
|
||||
$('#search_time button:eq(0)').addClass('cur');
|
||||
$('#search_time button').click(function(){
|
||||
$('#search_time button').each(function(){
|
||||
if ($(this).hasClass('cur')){
|
||||
$(this).removeClass('cur');
|
||||
}
|
||||
});
|
||||
$('#time_choose').attr("data-name",'');
|
||||
$('#time_choose').removeClass("cur");
|
||||
|
||||
$(this).addClass('cur');
|
||||
|
||||
wafLogRequest(1);
|
||||
});
|
||||
|
||||
owPost('get_default_site',{},function(rdata){
|
||||
$('select[name="site"]').html('');
|
||||
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
var rdata = rdata.data;
|
||||
var default_site = rdata["default"];
|
||||
var select = '';
|
||||
for (var i = 0; i < rdata["list"].length; i++) {
|
||||
if (default_site == rdata["list"][i]){
|
||||
select += '<option value="'+rdata["list"][i]+'" selected>'+rdata["list"][i]+'</option>';
|
||||
} else{
|
||||
select += '<option value="'+rdata["list"][i]+'">'+rdata["list"][i]+'</option>';
|
||||
}
|
||||
}
|
||||
$('select[name="site"]').html(select);
|
||||
wafLogRequest(1);
|
||||
|
||||
$('select[name="site"]').change(function(){
|
||||
wafLogRequest(1);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
var con = '<button class="btn btn-success btn-sm" onclick="UncoverAll()">解封所有</button>';
|
||||
con += '<div class="divtable mt10">\
|
||||
<table class="table table-hover waftable" style="color:#fff;">\
|
||||
<thead><tr><th width="18%">开始时间</th>\
|
||||
<th width="44%">IP</th>\
|
||||
<th width="10%">站点</th>\
|
||||
<th width="10%">封锁原因</th>\
|
||||
<th width="10%">封锁时长</th>\
|
||||
<th style="text-align: center;" width="10%">状态</th>\
|
||||
</thead>\
|
||||
</table>\
|
||||
</div>';
|
||||
$(".soft-man-con").html(con);
|
||||
}
|
||||
|
||||
|
||||
function wafLogs(){
|
||||
function wafOpLogs(){
|
||||
var con = '<div class="divtable">\
|
||||
<table class="table table-hover waftable" style="color:#fff;">\
|
||||
<thead><tr><th width="18%">名称</th>\
|
||||
|
||||
Executable
+29
@@ -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
|
||||
Executable
+18
@@ -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,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)
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
# coding:utf-8
|
||||
|
||||
import sys
|
||||
import io
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
+315
-7
@@ -6,14 +6,322 @@ import os
|
||||
import time
|
||||
import json
|
||||
|
||||
|
||||
TEST_URL = "t1.cn"
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
import string
|
||||
import json
|
||||
import hashlib
|
||||
import shlex
|
||||
import datetime
|
||||
import subprocess
|
||||
import re
|
||||
from random import Random
|
||||
|
||||
|
||||
def run():
|
||||
print('op lua run ok')
|
||||
TEST_URL = "http://t1.cn/"
|
||||
# TEST_URL = "https://www.zzzvps.com/"
|
||||
|
||||
|
||||
def writeFile(filename, str):
|
||||
# 写文件内容
|
||||
try:
|
||||
fp = open(filename, 'w+')
|
||||
fp.write(str)
|
||||
fp.close()
|
||||
return True
|
||||
except Exception as e:
|
||||
return False
|
||||
|
||||
|
||||
def httpGet(url, timeout=10):
|
||||
import urllib.request
|
||||
|
||||
try:
|
||||
req = urllib.request.urlopen(url, timeout=timeout)
|
||||
result = req.read().decode('utf-8')
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
|
||||
def httpGet__Header(url, headers, timeout=10):
|
||||
import urllib.request
|
||||
try:
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = urllib.request.urlopen(req)
|
||||
result = response.read().decode('utf-8')
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
|
||||
def httpUpload(url, timeout=10):
|
||||
try:
|
||||
import requests
|
||||
|
||||
files = {
|
||||
'file': open('/Users/midoks/Desktop/mwdev/server/op_waf/version.pl', 'rb')
|
||||
}
|
||||
res = requests.post(url=url, files=files)
|
||||
return res
|
||||
except Exception as e:
|
||||
return "http.upload:" + str(e)
|
||||
|
||||
|
||||
def httpUploadPhp(url, timeout=10):
|
||||
try:
|
||||
import requests
|
||||
|
||||
writeFile("/tmp/tmp.php", "")
|
||||
|
||||
files = {
|
||||
'file': open('/tmp/tmp.php', 'rb')
|
||||
}
|
||||
res = requests.post(url=url, files=files)
|
||||
return res
|
||||
except Exception as e:
|
||||
return "http.upload:" + str(e)
|
||||
|
||||
|
||||
def httpUploadPhpData(url, timeout=10):
|
||||
try:
|
||||
import requests
|
||||
|
||||
writeFile("/tmp/tmp.py", "<?php echo '123123';?>")
|
||||
|
||||
files = {
|
||||
'file': open('/tmp/tmp.py', 'rb')
|
||||
}
|
||||
res = requests.post(url=url, files=files)
|
||||
return res
|
||||
except Exception as e:
|
||||
return "http.upload:" + str(e)
|
||||
|
||||
|
||||
def httpGet__UA(url, ua, timeout=10):
|
||||
import urllib.request
|
||||
headers = {'user-agent': ua}
|
||||
try:
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = urllib.request.urlopen(req)
|
||||
result = response.read().decode('utf-8')
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
|
||||
def httpGet__cdn(url, ip, timeout=10):
|
||||
import urllib.request
|
||||
headers = {'x-forwarded-for': ip}
|
||||
try:
|
||||
req = urllib.request.Request(url, headers=headers)
|
||||
response = urllib.request.urlopen(req)
|
||||
result = response.read().decode('utf-8')
|
||||
return result
|
||||
|
||||
except Exception as e:
|
||||
return str(e)
|
||||
|
||||
|
||||
def httpPost(url, data, timeout=10):
|
||||
"""
|
||||
发送POST请求
|
||||
@url 被请求的URL地址(必需)
|
||||
@data POST参数,可以是字符串或字典(必需)
|
||||
@timeout 超时时间默认60秒
|
||||
return string
|
||||
"""
|
||||
if sys.version_info[0] == 2:
|
||||
try:
|
||||
import urllib
|
||||
import urllib2
|
||||
import ssl
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
data = urllib.urlencode(data)
|
||||
req = urllib2.Request(url, data)
|
||||
response = urllib2.urlopen(req, timeout=timeout)
|
||||
return response.read()
|
||||
except Exception as ex:
|
||||
return str(ex)
|
||||
else:
|
||||
try:
|
||||
import urllib.request
|
||||
import ssl
|
||||
try:
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
except:
|
||||
pass
|
||||
data = urllib.parse.urlencode(data).encode('utf-8')
|
||||
req = urllib.request.Request(url, data)
|
||||
response = urllib.request.urlopen(req, timeout=timeout)
|
||||
result = response.read()
|
||||
if type(result) == bytes:
|
||||
result = result.decode('utf-8')
|
||||
return result
|
||||
except Exception as ex:
|
||||
return str(ex)
|
||||
|
||||
|
||||
def test_Dir():
|
||||
'''
|
||||
目录保存
|
||||
'''
|
||||
url = TEST_URL + '?t=../etc/passwd'
|
||||
print("args test start")
|
||||
url_val = httpGet(url, 10)
|
||||
print(url_val)
|
||||
print("args test end")
|
||||
|
||||
|
||||
def test_UA():
|
||||
'''
|
||||
user-agent 过滤
|
||||
'''
|
||||
url = TEST_URL
|
||||
print("user-agent test start")
|
||||
url_val = httpGet__UA(url, 'ApacheBench')
|
||||
print(url_val)
|
||||
print("user-agent test end")
|
||||
|
||||
|
||||
def test_Header():
|
||||
'''
|
||||
user-agent 过滤
|
||||
'''
|
||||
url = TEST_URL
|
||||
print("user-agent test start")
|
||||
url_val = httpGet__Header(url, {'X-forwarded-For': '../etc/passwd'})
|
||||
print(url_val)
|
||||
print("user-agent test end")
|
||||
|
||||
|
||||
def test_UA_for(num):
|
||||
'''
|
||||
user-agent 过滤
|
||||
'''
|
||||
url = TEST_URL
|
||||
print("user-agent test start")
|
||||
for x in range(num):
|
||||
url_val = httpGet__UA(url, 'ApacheBench')
|
||||
print(url_val)
|
||||
print("user-agent test end")
|
||||
|
||||
|
||||
def test_cdn():
|
||||
'''
|
||||
user-agent 过滤
|
||||
'''
|
||||
url = TEST_URL
|
||||
print("cdn test start")
|
||||
url_val = httpGet__cdn(url, '2409:8a62:e20:95f0:45b7:233e:f003:c0ab')
|
||||
print(url_val)
|
||||
|
||||
url_val2 = httpGet__cdn(url, '91.245.227.173')
|
||||
print(url_val2)
|
||||
print("cdn test end")
|
||||
|
||||
|
||||
def test_POST():
|
||||
'''
|
||||
user-agent 过滤
|
||||
'''
|
||||
url = TEST_URL
|
||||
print("POST test start")
|
||||
url_val = httpPost(url, {'data': "substr($mmsss,0,1)"})
|
||||
# url_val = httpPost(url, {'data': "123123"})
|
||||
print(url_val)
|
||||
print("POST test end")
|
||||
|
||||
|
||||
def test_scan():
|
||||
'''
|
||||
目录保存
|
||||
'''
|
||||
url = TEST_URL + 'acunetix_wvs_security_test?t=1'
|
||||
print("scan test start")
|
||||
url_val = httpGet(url, 10)
|
||||
print(url_val)
|
||||
print("scan test end")
|
||||
|
||||
|
||||
def test_CC():
|
||||
'''
|
||||
目录保存
|
||||
'''
|
||||
url = TEST_URL + 'ok.txt'
|
||||
print("CC test start")
|
||||
|
||||
for x in range(122):
|
||||
url_val = httpGet(url, 10)
|
||||
print(url_val)
|
||||
|
||||
print("CC test end")
|
||||
|
||||
|
||||
def test_url_ext():
|
||||
'''
|
||||
目录保存
|
||||
'''
|
||||
url = TEST_URL + 't.sql'
|
||||
print("url_ext start")
|
||||
url_val = httpGet(url, 10)
|
||||
print(url_val)
|
||||
|
||||
print("url_ext end")
|
||||
|
||||
|
||||
def test_OK():
|
||||
'''
|
||||
目录保存
|
||||
'''
|
||||
url = TEST_URL
|
||||
print("ok test start")
|
||||
url_val = httpGet(url, 10)
|
||||
print(url_val)
|
||||
print("ok test end")
|
||||
|
||||
|
||||
def test_Upload():
|
||||
'''
|
||||
上传文件
|
||||
'''
|
||||
url = TEST_URL
|
||||
print("upload test start")
|
||||
url_val = httpUpload(url, 10)
|
||||
print(url_val)
|
||||
|
||||
print("upload test end")
|
||||
|
||||
print("upload php test start")
|
||||
url_val = httpUploadPhp(url, 10)
|
||||
print(url_val)
|
||||
print("upload php test start")
|
||||
|
||||
print("upload php data test start")
|
||||
url_val = httpUploadPhpData(url, 10)
|
||||
print(url_val)
|
||||
print("upload php data test start")
|
||||
|
||||
|
||||
def test_start():
|
||||
# test_OK()
|
||||
# test_Dir()
|
||||
# test_UA()
|
||||
test_Header()
|
||||
# test_UA_for(1000)
|
||||
test_POST()
|
||||
test_scan()
|
||||
# test_CC()
|
||||
# test_url_ext()
|
||||
# test_cdn()
|
||||
# test_Upload()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
if action == "run":
|
||||
run()
|
||||
os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/plugins/op_waf && sh install.sh uninstall 0.2.2 && sh install.sh install 0.2.2')
|
||||
os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/ && python3 plugins/openresty/index.py stop && python3 plugins/openresty/index.py start')
|
||||
test_start()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
```
|
||||
|
||||
@@ -2,6 +2,21 @@
|
||||
PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin
|
||||
export PATH
|
||||
|
||||
# apt -y install apache2-utils
|
||||
# yum -y install httpd-tools
|
||||
|
||||
# ab -c 3000 -n 10000000 http://www.zzzvps.com/
|
||||
# /cc https://www.zzzvps.com/ 120
|
||||
# ab -c 10 -n 1000 http://t1.cn/wp-admin/index.php
|
||||
# ab -c 1000 -n 1000000 http://dev156.cachecha.com/
|
||||
|
||||
curPath=`pwd`
|
||||
rootPath=$(dirname "$curPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
rootPath=$(dirname "$rootPath")
|
||||
|
||||
if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
python3 index.py
|
||||
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ def createBgTask():
|
||||
removeBgTask()
|
||||
args = {
|
||||
"period": "minute-n",
|
||||
"minute-n": "3",
|
||||
"minute-n": "1",
|
||||
}
|
||||
createBgTaskByName(getPluginName(), args)
|
||||
|
||||
@@ -71,7 +71,7 @@ def createBgTaskByName(name, args):
|
||||
print("计划任务已经存在!")
|
||||
return True
|
||||
import crontab_api
|
||||
api = crontab_api.crontab_api()
|
||||
cron_api = crontab_api.crontab_api()
|
||||
|
||||
period = args['period']
|
||||
_hour = ''
|
||||
@@ -87,16 +87,18 @@ def createBgTaskByName(name, args):
|
||||
_where1 = args['minute-n']
|
||||
_minute = ''
|
||||
|
||||
mw_dir = mw.getRunDir()
|
||||
cmd = '''
|
||||
mw_dir=%s
|
||||
rname=%s
|
||||
plugin_path=%s
|
||||
script_path=%s
|
||||
logs_file=$plugin_path/${rname}.log
|
||||
''' % (name, getServerDir(), getPluginDir())
|
||||
''' % (mw_dir, name, getServerDir(), getPluginDir())
|
||||
cmd += 'echo "★【`date +"%Y-%m-%d %H:%M:%S"`】 STSRT★" >> $logs_file' + "\n"
|
||||
cmd += 'echo ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" >> $logs_file' + "\n"
|
||||
cmd += 'echo "python3 $script_path/tool_task.py run >> $logs_file 2>&1"' + "\n"
|
||||
cmd += '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 += 'cd $mw_dir && source bin/activate && python3 $script_path/tool_task.py run >> $logs_file 2>&1' + "\n"
|
||||
cmd += 'echo "【`date +"%Y-%m-%d %H:%M:%S"`】 END★" >> $logs_file' + "\n"
|
||||
cmd += 'echo "<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<" >> $logs_file' + "\n"
|
||||
|
||||
@@ -115,7 +117,7 @@ logs_file=$plugin_path/${rname}.log
|
||||
'urladdress': '',
|
||||
}
|
||||
|
||||
task_id = api.add(params)
|
||||
task_id = cron_api.add(params)
|
||||
if task_id > 0:
|
||||
cfg["task_id"] = task_id
|
||||
cfg["name"] = name
|
||||
@@ -144,8 +146,15 @@ def removeBgTask():
|
||||
return False
|
||||
|
||||
|
||||
def getCpuUsed():
|
||||
import psutil
|
||||
used = psutil.cpu_percent(interval=1)
|
||||
path = getServerDir() + "/cpu.info"
|
||||
mw.writeFile(path, str(int(used)))
|
||||
|
||||
|
||||
def run():
|
||||
print('op lua run ok')
|
||||
getCpuUsed()
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) > 1:
|
||||
|
||||
Executable
+1
@@ -0,0 +1 @@
|
||||
自动生成配置文件
|
||||
@@ -1 +1 @@
|
||||
{"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "\u8fc7\u6ee4\u5e38\u89c1\u626b\u63cf\u6d4b\u8bd5\u5de5\u5177\u7684\u6e17\u900f\u6d4b\u8bd5", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "\u8fc7\u8651CC\u653b\u51fb", "limit": 120, "endtime": 300, "open": true, "reqfile": "", "cycle": 60}, "get": {"status": 403, "ps": "\u8fc7\u6ee4uri\u3001uri\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 403, "ps": "\u901a\u5e38\u7528\u4e8e\u8fc7\u6ee4\u6d4f\u89c8\u5668\u3001\u8718\u86db\u53ca\u4e00\u4e9b\u81ea\u52a8\u626b\u63cf\u5668", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 403, "ps": "\u5176\u5b83\u975e\u901a\u7528\u8fc7\u6ee4", "reqfile": "other.html"}, "cookie": {"status": 403, "ps": "\u8fc7\u6ee4\u5229\u7528Cookie\u53d1\u8d77\u7684\u6e17\u900f\u653b\u51fb", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/btwaf", "post": {"status": 403, "ps": "\u8fc7\u6ee4POST\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "post.html"}, "open": true}
|
||||
{"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "过滤常见扫描测试工具的渗透测试", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "过虑CC攻击", "limit": 120, "endtime": 300, "open": true,"cycle": 60}, "safe_verify":{"status": 200,"ps": "强制安全校验", "reqfile": "safe_js.html","open": false,"cpu":50,"auto":true,"time":86400 },"get": {"status": 200, "ps": "过滤uri、uri参数中常见sql注入、xss等攻击", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 200, "ps": "通常用于过滤浏览器、蜘蛛及一些自动扫描器", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 200, "ps": "其它非通用过滤", "reqfile": "other.html"}, "cookie": {"status": 200, "ps": "过滤利用Cookie发起的渗透攻击", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/waf", "post": {"status": 200, "ps": "过滤POST参数中常见sql注入、xss等攻击", "open": true, "reqfile": "post.html"}, "open": true}
|
||||
@@ -7,7 +7,7 @@
|
||||
*{margin:0;padding:0;color:#444}
|
||||
body{font-size:14px;font-family:"宋体"}
|
||||
.main{width:600px;margin:10% auto;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
|
||||
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
|
||||
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
|
||||
.t2{margin-bottom:8px; font-weight:bold}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*{margin:0;padding:0;color:#444}
|
||||
body{font-size:14px;font-family:"宋体"}
|
||||
.main{width:600px;margin:10% auto;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
|
||||
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
|
||||
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
|
||||
.t2{margin-bottom:8px; font-weight:bold}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*{margin:0;padding:0;color:#444}
|
||||
body{font-size:14px;font-family:"宋体"}
|
||||
.main{width:600px;margin:10% auto;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
|
||||
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
|
||||
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
|
||||
.t2{margin-bottom:8px; font-weight:bold}
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*{margin:0;padding:0;color:#444}
|
||||
body{font-size:14px;font-family:"宋体"}
|
||||
.main{width:600px;margin:10% auto;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
|
||||
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
|
||||
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
|
||||
.t2{margin-bottom:8px; font-weight:bold}
|
||||
|
||||
Executable
+151
@@ -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>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*{margin:0;padding:0;color:#444}
|
||||
body{font-size:14px;font-family:"宋体"}
|
||||
.main{width:600px;margin:10% auto;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;padding-left: 20px;}
|
||||
.title{background: #20a53a;color: #fff;font-size: 16px;height: 40px;line-height: 40px;text-align: center;}
|
||||
.content{background-color:#f3f7f9; height:280px;border:1px dashed #c6d9b6;padding:20px}
|
||||
.t1{border-bottom: 1px dashed #c6d9b6;color: #ff4000;font-weight: bold; margin: 0 0 20px; padding-bottom: 18px;}
|
||||
.t2{margin-bottom:8px; font-weight:bold}
|
||||
|
||||
+494
-182
@@ -1,26 +1,255 @@
|
||||
|
||||
local setmetatable = setmetatable
|
||||
local _M = { _VERSION = '0.01' }
|
||||
local _M = { _VERSION = '0.02' }
|
||||
local mt = { __index = _M }
|
||||
|
||||
local json = require "cjson"
|
||||
local sqlite3 = require "lsqlite3"
|
||||
|
||||
local ngx_match = ngx.re.find
|
||||
local debug_mode = false
|
||||
|
||||
local waf_root = "{$WAF_ROOT}"
|
||||
local cpath = waf_root.."/waf/"
|
||||
local log_dir = waf_root.."/logs/"
|
||||
local rpath = cpath.."/rule/"
|
||||
|
||||
function _M.new(self, cpath, rpath, logdir)
|
||||
-- ngx.log(ngx.ERR,"read:"..cpath..",rpath:"..rpath)
|
||||
local opt = {
|
||||
cpath = cpath,
|
||||
rpath = rpath,
|
||||
logdir = logdir,
|
||||
config = '',
|
||||
site_config = '',
|
||||
params = nil
|
||||
function _M.new(self)
|
||||
|
||||
local self = {
|
||||
waf_root = waf_root,
|
||||
cpath = cpath,
|
||||
rpath = rpath,
|
||||
logdir = log_dir,
|
||||
config = '',
|
||||
site_config = '',
|
||||
server_name = '',
|
||||
global_tatal = nil,
|
||||
params = nil,
|
||||
}
|
||||
local p = setmetatable(opt, mt)
|
||||
return p
|
||||
return setmetatable(self, mt)
|
||||
end
|
||||
|
||||
|
||||
function _M.getInstance(self)
|
||||
if rawget(self, "instance") == nil then
|
||||
rawset(self, "instance", self:new())
|
||||
|
||||
if 0 == ngx.worker.id() then
|
||||
self:cron()
|
||||
end
|
||||
end
|
||||
assert(self.instance ~= nil)
|
||||
return self.instance
|
||||
end
|
||||
|
||||
function _M.initDB(self)
|
||||
local path = log_dir .. "/waf.db"
|
||||
db, err = sqlite3.open(path)
|
||||
|
||||
if err then
|
||||
self:D("initDB err:"..tostring(err))
|
||||
return nil
|
||||
end
|
||||
|
||||
db:exec([[PRAGMA synchronous = 0]])
|
||||
db:exec([[PRAGMA cache_size = 8000]])
|
||||
db:exec([[PRAGMA page_size = 32768]])
|
||||
db:exec([[PRAGMA journal_mode = wal]])
|
||||
db:exec([[PRAGMA journal_size_limit = 1073741824]])
|
||||
return db
|
||||
end
|
||||
|
||||
-- 后台任务
|
||||
function _M.cron(self)
|
||||
local timer_every_get_data = function (premature)
|
||||
self.clean_log()
|
||||
end
|
||||
ngx.timer.every(10, timer_every_get_data)
|
||||
|
||||
local timer_every_import_data = function (premature)
|
||||
|
||||
local llen, _ = ngx.shared.waf_limit:llen('waf_limit_logs')
|
||||
if llen == 0 then
|
||||
return true
|
||||
end
|
||||
|
||||
local db = self:initDB()
|
||||
|
||||
local stmt2 = db:prepare[[INSERT INTO logs(time, ip, domain, server_name, method, status_code, uri, user_agent, rule_name, reason)
|
||||
VALUES(:time, :ip, :domain, :server_name, :method, :status_code, :uri, :user_agent, :rule_name, :reason)]]
|
||||
|
||||
db:exec([[BEGIN TRANSACTION]])
|
||||
|
||||
for i=1,llen do
|
||||
local data, _ = ngx.shared.waf_limit:lpop('waf_limit_logs')
|
||||
-- self:D("waf_limit_logs:"..data)
|
||||
if not data then
|
||||
break
|
||||
end
|
||||
|
||||
local info = json.decode(data)
|
||||
|
||||
stmt2:bind_names{
|
||||
time=info["time"],
|
||||
ip=info["ip"],
|
||||
domain=info["server_name"],
|
||||
server_name=info["server_name"],
|
||||
method=info["method"],
|
||||
status_code=info["status_code"],
|
||||
user_agent=info["user_agent"],
|
||||
uri=info["request_uri"],
|
||||
rule_name=info['rule_name'],
|
||||
reason=info['reason']
|
||||
}
|
||||
|
||||
local res, err = stmt2:step()
|
||||
if tostring(res) == "5" then
|
||||
self.D("waf the step database connection is busy, so it will be stored later.")
|
||||
return false
|
||||
end
|
||||
stmt2:reset()
|
||||
end
|
||||
|
||||
local res, err = db:execute([[COMMIT]])
|
||||
if db and db:isopen() then
|
||||
db:close()
|
||||
end
|
||||
|
||||
end
|
||||
ngx.timer.every(0.5, timer_every_import_data)
|
||||
end
|
||||
|
||||
|
||||
function _M.clean_log(self)
|
||||
local db = self:initDB()
|
||||
local now_date = os.date("*t")
|
||||
local save_day = 90
|
||||
local save_date_timestamp = os.time{year=now_date.year,
|
||||
month=now_date.month, day=now_date.day-save_day, hour=0}
|
||||
-- delete expire data
|
||||
db:exec("DELETE FROM web_logs WHERE time<"..tostring(save_date_timestamp))
|
||||
end
|
||||
|
||||
function _M.log(self, args, rule_name, reason)
|
||||
|
||||
args["rule_name"] = rule_name
|
||||
args["reason"] = reason
|
||||
|
||||
local push_data = json.encode(args)
|
||||
|
||||
ngx.shared.waf_limit:rpush("waf_limit_logs", push_data)
|
||||
-- self:D("push_data:"..push_data)
|
||||
|
||||
-- local db = self:initDB()
|
||||
|
||||
-- local stmt2 = db:prepare[[INSERT INTO logs(time, ip, domain, server_name, method, status_code, uri, user_agent, rule_name, reason)
|
||||
-- VALUES(:time, :ip, :domain, :server_name, :method, :status_code, :uri, :user_agent, :rule_name, :reason)]]
|
||||
|
||||
-- db:exec([[BEGIN TRANSACTION]])
|
||||
|
||||
-- stmt2:bind_names{
|
||||
-- time=args["time"],
|
||||
-- ip=args["ip"],
|
||||
-- domain=args["server_name"],
|
||||
-- server_name=args["server_name"],
|
||||
-- method=args["method"],
|
||||
-- status_code=args["status_code"],
|
||||
-- user_agent=args["user_agent"],
|
||||
-- uri=args["request_uri"],
|
||||
-- rule_name=rule_name,
|
||||
-- reason=reason
|
||||
-- }
|
||||
|
||||
-- local res, err = stmt2:step()
|
||||
-- -- self:D("LOG[1]:"..tostring(res)..":"..tostring(err))
|
||||
|
||||
-- if tostring(res) == "5" then
|
||||
-- self.D("waf the step database connection is busy, so it will be stored later.")
|
||||
-- return false
|
||||
-- end
|
||||
-- stmt2:reset()
|
||||
|
||||
-- local res, err = db:execute([[COMMIT]])
|
||||
-- -- self:D("LOG[2]:"..tostring(res)..":"..tostring(err))
|
||||
-- if db and db:isopen() then
|
||||
-- db:close()
|
||||
-- end
|
||||
-- return true
|
||||
end
|
||||
|
||||
|
||||
function _M.setDebug(self, mode)
|
||||
debug_mode = mode
|
||||
end
|
||||
|
||||
|
||||
-- 调试方式
|
||||
function _M.D(self, msg)
|
||||
if not debug_mode then return true end
|
||||
|
||||
local _msg = ''
|
||||
if type(msg) == 'table' then
|
||||
for key, val in pairs(msg) do
|
||||
_msg = tostring( key)..':'.."\n"
|
||||
end
|
||||
elseif type(msg) == 'string' then
|
||||
_msg = msg
|
||||
elseif type(msg) == 'nil' then
|
||||
_msg = 'nil'
|
||||
else
|
||||
_msg = msg
|
||||
end
|
||||
|
||||
|
||||
local fp = io.open(waf_root.."/debug.log", "ab")
|
||||
if fp == nil then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- local localtime = os.date("%Y-%m-%d %H:%M:%S")
|
||||
local localtime = ngx.localtime()
|
||||
if server_name then
|
||||
fp:write(tostring(_msg) .. "\n")
|
||||
else
|
||||
fp:write(localtime..":"..tostring(_msg) .. "\n")
|
||||
end
|
||||
|
||||
fp:flush()
|
||||
fp:close()
|
||||
return true
|
||||
end
|
||||
|
||||
function _M.is_working(self,sign)
|
||||
local work_status = ngx.shared.waf_limit:get(sign.."_working")
|
||||
if work_status ~= nil and work_status == true then
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function _M.lock_working(self, sign)
|
||||
local working_key = sign.."_working"
|
||||
ngx.shared.waf_limit:set(working_key, true, 60)
|
||||
end
|
||||
|
||||
function _M.unlock_working(self, sign)
|
||||
local working_key = sign.."_working"
|
||||
ngx.shared.waf_limit:set(working_key, false)
|
||||
end
|
||||
|
||||
|
||||
local function write_file_clear(filename, body)
|
||||
fp = io.open(filename,'w')
|
||||
if fp == nil then
|
||||
return nil
|
||||
end
|
||||
fp:write(body)
|
||||
fp:flush()
|
||||
fp:close()
|
||||
return true
|
||||
end
|
||||
|
||||
function _M.setConfData( self, config, site_config )
|
||||
self.config = config
|
||||
self.site_config = site_config
|
||||
@@ -64,11 +293,11 @@ function _M.is_max(self,ip1,ip2)
|
||||
end
|
||||
|
||||
function _M.split(self, str,reps )
|
||||
local resultStrList = {}
|
||||
local rsList = {}
|
||||
string.gsub(str,'[^'..reps..']+',function(w)
|
||||
table.insert(resultStrList,w)
|
||||
table.insert(rsList,w)
|
||||
end)
|
||||
return resultStrList
|
||||
return rsList
|
||||
end
|
||||
|
||||
function _M.arrip(self, ipstr)
|
||||
@@ -94,28 +323,41 @@ function _M.compare_ip(self,ips)
|
||||
end
|
||||
|
||||
|
||||
function _M.return_message(self, status, msg)
|
||||
ngx.header.content_type = "application/json;"
|
||||
ngx.status = status
|
||||
ngx.say(json.encode(msg))
|
||||
ngx.exit(status)
|
||||
|
||||
function _M.to_json(self, msg)
|
||||
return json.encode(msg)
|
||||
end
|
||||
|
||||
function _M.return_state(status,msg)
|
||||
result = {}
|
||||
result['status'] = status
|
||||
result['msg'] = msg
|
||||
return result
|
||||
end
|
||||
|
||||
function _M.return_html(self,status,html)
|
||||
function _M.return_message(self, status, msg)
|
||||
ngx.header.content_type = "application/json"
|
||||
local data = self:return_state(status, msg)
|
||||
ngx.say(json.encode(data))
|
||||
ngx.exit(200)
|
||||
end
|
||||
|
||||
function _M.return_html(self, status, html)
|
||||
ngx.header.content_type = "text/html"
|
||||
ngx.status = status
|
||||
ngx.say(html)
|
||||
status = tonumber(status)
|
||||
-- self:D("return_html:"..tostring(status))
|
||||
if status == 200 then
|
||||
ngx.say(html)
|
||||
end
|
||||
ngx.exit(status)
|
||||
end
|
||||
|
||||
function _M.read_file_body(self, filename)
|
||||
-- ngx.log(ngx.ERR,"read_file_body:"..filename)
|
||||
fp = io.open(filename, 'r')
|
||||
if fp == nil then
|
||||
return nil
|
||||
end
|
||||
fbody = fp:read("*a")
|
||||
local fbody = fp:read("*a")
|
||||
fp:close()
|
||||
if fbody == '' then
|
||||
return nil
|
||||
@@ -123,7 +365,38 @@ function _M.read_file_body(self, filename)
|
||||
return fbody
|
||||
end
|
||||
|
||||
function _M.read_file(self, name)
|
||||
f = self.rpath .. name .. '.json'
|
||||
local fbody = self:read_file_body(f)
|
||||
if fbody == nil then
|
||||
return {}
|
||||
end
|
||||
|
||||
local data = json.decode(fbody)
|
||||
return data
|
||||
end
|
||||
|
||||
|
||||
function _M.select_rule(self, rules)
|
||||
if not rules then return {} end
|
||||
new_rules = {}
|
||||
for i,v in ipairs(rules)
|
||||
do
|
||||
if v[1] == 1 then
|
||||
table.insert(new_rules,v[2])
|
||||
end
|
||||
end
|
||||
return new_rules
|
||||
end
|
||||
|
||||
function _M.read_file_table( self, name )
|
||||
return self:select_rule(self:read_file(name))
|
||||
end
|
||||
|
||||
|
||||
function _M.read_file_body_decode(self, name)
|
||||
return json.decode(self:read_file_body(name))
|
||||
end
|
||||
|
||||
function _M.write_file(self, filename, body)
|
||||
fp = io.open(filename,'ab')
|
||||
@@ -137,34 +410,9 @@ function _M.write_file(self, filename, body)
|
||||
end
|
||||
|
||||
function _M.write_file_clear(self, filename, body)
|
||||
fp = io.open(filename,'w')
|
||||
if fp == nil then
|
||||
return nil
|
||||
end
|
||||
fp:write(body)
|
||||
fp:flush()
|
||||
fp:close()
|
||||
return true
|
||||
return write_file_clear(filename, body)
|
||||
end
|
||||
|
||||
|
||||
function _M.write_drop_ip(self, is_drop, drop_time)
|
||||
local filename = self.cpath .. 'drop_ip.log'
|
||||
local fp = io.open(filename,'ab')
|
||||
local server_name = self.params["server_name"]
|
||||
local ip = self.params["server_name"]
|
||||
local request_uri = self.params["request_uri"]
|
||||
|
||||
if fp == nil then return false end
|
||||
local logtmp = {os.time(),ip,server_name,request_uri,drop_time,is_drop}
|
||||
local logstr = json.encode(logtmp) .. "\n"
|
||||
fp:write(logstr)
|
||||
fp:flush()
|
||||
fp:close()
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function _M.write_to_file(self, logstr)
|
||||
local server_name = self.params['server_name']
|
||||
local filename = self.logdir .. '/' .. server_name .. '_' .. ngx.today() .. '.log'
|
||||
@@ -172,10 +420,19 @@ function _M.write_to_file(self, logstr)
|
||||
return true
|
||||
end
|
||||
|
||||
-- 是否文件迁入数据库中
|
||||
function _M.is_migrating(self)
|
||||
local migrating = self.waf_root +"/migrating"
|
||||
local file = io.open(migrating, "rb")
|
||||
if file then return true end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function _M.continue_key(self,key)
|
||||
key = tostring(key)
|
||||
if string.len(key) > 64 then return false end;
|
||||
local keys = {"content","contents","body","msg","file","files","img","newcontent"}
|
||||
local keys = { "content", "contents", "body", "msg", "file", "files", "img", "newcontent" }
|
||||
for _,k in ipairs(keys)
|
||||
do
|
||||
if k == key then return false end;
|
||||
@@ -195,7 +452,7 @@ function _M.array_len(self, arr)
|
||||
end
|
||||
|
||||
function _M.is_ipaddr(self, client_ip)
|
||||
local cipn = split(client_ip,'.')
|
||||
local cipn = self:split(client_ip,'.')
|
||||
if self:array_len(cipn) < 4 then return false end
|
||||
for _,v in ipairs({1,2,3,4})
|
||||
do
|
||||
@@ -206,47 +463,31 @@ function _M.is_ipaddr(self, client_ip)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function _M.read_file_body_decode(self, filename)
|
||||
return json.decode(self:read_file_body(filename))
|
||||
end
|
||||
|
||||
function _M.select_rule(self, rules)
|
||||
if not rules then return {} end
|
||||
new_rules = {}
|
||||
for i,v in ipairs(rules)
|
||||
do
|
||||
if v[1] == 1 then
|
||||
table.insert(new_rules,v[2])
|
||||
end
|
||||
end
|
||||
return new_rules
|
||||
end
|
||||
|
||||
|
||||
function _M.read_file(self, name)
|
||||
f = self.rpath .. name .. '.json'
|
||||
fbody = self:read_file_body(f)
|
||||
if fbody == nil then
|
||||
return {}
|
||||
end
|
||||
return json.decode(fbody)
|
||||
end
|
||||
|
||||
function _M.read_file_table( self, name )
|
||||
return self:select_rule(self:read_file('args'))
|
||||
end
|
||||
|
||||
|
||||
function _M.inc_log(self, name, rule)
|
||||
local server_name = self.params['server_name']
|
||||
-- 定时异步同步统计信息
|
||||
function _M.timer_stats_total(self)
|
||||
local total_path = self.cpath .. 'total.json'
|
||||
local tbody = ngx.shared.limit:get(total_path)
|
||||
if not tbody then
|
||||
tbody = self:read_file_body(total_path)
|
||||
if not tbody then return false end
|
||||
local total = ngx.shared.waf_limit:get(total_path)
|
||||
if not total then
|
||||
return false
|
||||
end
|
||||
local total = json.decode(tbody)
|
||||
return self:write_file_clear(total_path,total)
|
||||
end
|
||||
|
||||
function _M.stats_total(self, name, rule)
|
||||
local server_name = self.params['server_name']
|
||||
local total_path = cpath .. 'total.json'
|
||||
local total = ngx.shared.waf_limit:get(total_path)
|
||||
|
||||
if not total then
|
||||
local tbody = self:read_file_body(total_path)
|
||||
total = json.decode(tbody)
|
||||
else
|
||||
total = json.decode(total)
|
||||
end
|
||||
|
||||
if not total then return false end
|
||||
|
||||
-- 开始计算
|
||||
if not total['sites'] then total['sites'] = {} end
|
||||
if not total['sites'][server_name] then total['sites'][server_name] = {} end
|
||||
if not total['sites'][server_name][name] then total['sites'][server_name][name] = 0 end
|
||||
@@ -256,84 +497,124 @@ function _M.inc_log(self, name, rule)
|
||||
total['total'] = total['total'] + 1
|
||||
total['sites'][server_name][name] = total['sites'][server_name][name] + 1
|
||||
total['rules'][name] = total['rules'][name] + 1
|
||||
local total_log = json.encode(total)
|
||||
if not total_log then return false end
|
||||
ngx.shared.limit:set(total_path,total_log)
|
||||
if not ngx.shared.limit:get('mw_waf_timeout') then
|
||||
self:write_file_clear(total_path,total_log)
|
||||
ngx.shared.limit:set('mw_waf_timeout',1,5)
|
||||
end
|
||||
|
||||
ngx.shared.waf_limit:set(total_path,json.encode(total))
|
||||
|
||||
-- 异步执行
|
||||
-- 现在改再init_workder.lua 定时执行
|
||||
-- ngx.timer.every(3, timer_stats_total_log)
|
||||
end
|
||||
|
||||
|
||||
---------------------------------------------------
|
||||
-- 获取配置域名
|
||||
function _M.get_sn(self, config_domains)
|
||||
local request_name = ngx.var.server_name
|
||||
local cache_name = ngx.shared.waf_limit:get(request_name)
|
||||
if cache_name then return cache_name end
|
||||
|
||||
function _M.get_server_name(self)
|
||||
local c_name = ngx.var.server_name
|
||||
local my_name = ngx.shared.limit:get(c_name)
|
||||
if my_name then return my_name end
|
||||
local tmp = self:read_file_body(self.cpath .. 'domains.json')
|
||||
if not tmp then return c_name end
|
||||
local domains = json.decode(tmp)
|
||||
for _,v in ipairs(domains)
|
||||
for _,v in ipairs(config_domains)
|
||||
do
|
||||
for _,d_name in ipairs(v['domains'])
|
||||
for _,cd_name in ipairs(v['domains'])
|
||||
do
|
||||
if c_name == d_name then
|
||||
ngx.shared.limit:set(c_name,v['name'],3600)
|
||||
if request_name == cd_name then
|
||||
ngx.shared.waf_limit:set(request_name,v['name'],86400)
|
||||
return v['name']
|
||||
end
|
||||
end
|
||||
end
|
||||
return c_name
|
||||
return request_name
|
||||
end
|
||||
|
||||
function _M.get_random(self,n)
|
||||
math.randomseed(ngx.time())
|
||||
local t = {
|
||||
"0","1","2","3","4","5","6","7","8","9",
|
||||
"a","b","c","d","e","f","g","h","i","j",
|
||||
"k","l","m","n","o","p","q","r","s","t",
|
||||
"u","v","w","x","y","z",
|
||||
"A","B","C","D","E","F","G","H","I","J",
|
||||
"K","L","M","N","O","P","Q","R","S","T",
|
||||
"U","V","W","X","Y","Z",
|
||||
}
|
||||
local s = ""
|
||||
for i =1, n do
|
||||
s = s .. t[math.random(#t)]
|
||||
end
|
||||
return s
|
||||
end
|
||||
|
||||
|
||||
-- function _M.get_sn(self)
|
||||
-- retun string.gsub(self:get_server_name(),'_','.')
|
||||
-- end
|
||||
|
||||
|
||||
function _M.is_ngx_match(self, rules, sbody, rule_name)
|
||||
if rules == nil or sbody == nil then return false end
|
||||
if type(sbody) == "string" then
|
||||
sbody = {sbody}
|
||||
end
|
||||
|
||||
if type(rules) == "string" then
|
||||
rules = {rules}
|
||||
function _M.is_ngx_match_orgin(self,rule, match, sign)
|
||||
if ngx_match(ngx.unescape_uri(match), rule, "isjo") then
|
||||
error_rule = rule .. ' >> ' .. sign .. ':' .. match
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
for k,body in pairs(sbody)
|
||||
|
||||
function _M.ngx_match_string(self, rule, content,sign)
|
||||
local t = self:is_ngx_match_orgin(rule, content, sign)
|
||||
if t then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
function _M.ngx_match_list(self, rules, content)
|
||||
local args_type = type(content)
|
||||
for i,rule in ipairs(rules)
|
||||
do
|
||||
if self:continue_key(k) then
|
||||
for i,rule in ipairs(rules)
|
||||
do
|
||||
if self.site_config[server_name] and rule_name then
|
||||
local n = i - 1
|
||||
for _,j in ipairs(self.site_config[server_name]['disable_rule'][rule_name])
|
||||
do
|
||||
if n == j then
|
||||
rule = ""
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if body and rule ~="" then
|
||||
if type(body) == "string" then
|
||||
if ngx_match(ngx.unescape_uri(body),rule,"isjo") then
|
||||
error_rule = rule .. ' >> ' .. k .. ':' .. body
|
||||
return true
|
||||
end
|
||||
end
|
||||
if type(k) == "string" then
|
||||
if ngx_match(ngx.unescape_uri(k),rule,"isjo") then
|
||||
error_rule = rule .. ' >> ' .. k
|
||||
return true
|
||||
end
|
||||
if rule[1] == 1 then
|
||||
if args_type == 'string' then
|
||||
-- self:D("string: "..tostring(rule[2])..":".. tostring(content)..":"..tostring(rule[3]))
|
||||
local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
|
||||
if t then
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
if args_type == 'table' then
|
||||
for _,arg_v in pairs(content) do
|
||||
-- self:D("table : "..tostring(rule[2])..":".. tostring(arg_v)..":"..tostring(rule[3]))
|
||||
local t = self:is_ngx_match_orgin(rule[2], arg_v, rule[3])
|
||||
if t then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function _M.is_ngx_match_ua(self, rules, content)
|
||||
-- ngx.header.content_type = "text/html"
|
||||
for i,rule in ipairs(rules)
|
||||
do
|
||||
-- 开启的规则,才匹配。
|
||||
if rule[1] == 1 then
|
||||
local t = self:is_ngx_match_orgin(rule[2], content, rule[3])
|
||||
if t then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function _M.is_ngx_match_post(self, rules, content)
|
||||
for i,rule in ipairs(rules)
|
||||
do
|
||||
-- 开启的规则,才匹配。
|
||||
if rule[1] == 1 then
|
||||
local t = self:is_ngx_match_orgin(rule[2],content, rule[3])
|
||||
if t then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
@@ -341,63 +622,84 @@ end
|
||||
|
||||
|
||||
function _M.write_log(self, name, rule)
|
||||
local ip = self.params['ip']
|
||||
local retry = self.config['retry']['retry']
|
||||
local retry_time = self.config['retry']['retry_time']
|
||||
local retry_cycle = self.config['retry']['retry_cycle']
|
||||
local config = self.config
|
||||
local params = self.params
|
||||
|
||||
local ip = params['ip']
|
||||
local ngx_time = ngx.time()
|
||||
|
||||
local count, _ = ngx.shared.drop_ip:get(ip)
|
||||
local retry = config['retry']['retry']
|
||||
local retry_time = config['retry']['retry_time']
|
||||
local retry_cycle = config['retry']['retry_cycle']
|
||||
|
||||
local count = ngx.shared.waf_drop_ip:get(ip)
|
||||
if count then
|
||||
ngx.shared.drop_ip:incr(ip,1)
|
||||
ngx.shared.waf_drop_ip:incr(ip, 1)
|
||||
else
|
||||
ngx.shared.drop_ip:set(ip,1,retry_cycle)
|
||||
ngx.shared.waf_drop_ip:set(ip, 1, retry_cycle)
|
||||
end
|
||||
if self.config['log'] ~= true or self:is_site_config('log') ~= true then return false end
|
||||
local method = ngx.req.get_method()
|
||||
|
||||
if config['log'] ~= true or self:is_site_config('log') ~= true then return false end
|
||||
local method = params['method']
|
||||
if error_rule then
|
||||
rule = error_rule
|
||||
error_rule = nil
|
||||
end
|
||||
|
||||
local logtmp = {ngx.localtime(), ip, method, ngx.var.request_uri, ngx.var.http_user_agent, name, rule}
|
||||
local logstr = json.encode(logtmp) .. "\n"
|
||||
local count,_ = ngx.shared.drop_ip:get(ip)
|
||||
if count > retry and name ~= 'cc' then
|
||||
local safe_count,_ = ngx.shared.drop_sum:get(ip)
|
||||
local count = ngx.shared.waf_drop_ip:get(ip)
|
||||
-- self:D("write_log; count:" ..tostring(count).. ",retry:" .. tostring(retry) )
|
||||
if (count > retry and name ~= 'cc') then
|
||||
local safe_count,_ = ngx.shared.waf_drop_sum:get(ip)
|
||||
if not safe_count then
|
||||
ngx.shared.drop_sum:set(ip,1,86400)
|
||||
ngx.shared.waf_drop_sum:set(ip, 1, 86400)
|
||||
safe_count = 1
|
||||
else
|
||||
ngx.shared.drop_sum:incr(ip,1)
|
||||
ngx.shared.waf_drop_sum:incr(ip, 1)
|
||||
end
|
||||
local lock_time = retry_time * safe_count
|
||||
if lock_time > 86400 then lock_time = 86400 end
|
||||
logtmp = {ngx.localtime(),ip,method,ngx.var.request_uri, ngx.var.http_user_agent,name,retry_cycle .. '秒以内累计超过'..retry..'次以上非法请求,封锁'.. lock_time ..'秒'}
|
||||
logstr = logstr .. json.encode(logtmp) .. "\n"
|
||||
ngx.shared.drop_ip:set(ip,retry+1,lock_time)
|
||||
self:write_drop_ip('inc',lock_time)
|
||||
|
||||
retry_times = retry + 1
|
||||
ngx.shared.waf_drop_ip:set(ip, retry_times, lock_time)
|
||||
|
||||
local reason = retry_cycle .. '秒以内累计超过'..retry..'次以上非法请求,封锁'.. lock_time ..'秒'
|
||||
self:log(params, name, reason)
|
||||
elseif name ~= 'cc' then
|
||||
self:log(params, name, rule)
|
||||
end
|
||||
self:write_to_file(logstr)
|
||||
self:inc_log(name,rule)
|
||||
|
||||
self:stats_total(name, rule)
|
||||
end
|
||||
|
||||
|
||||
function _M.get_client_ip(self)
|
||||
function _M.get_real_ip(self, server_name)
|
||||
local client_ip = "unknown"
|
||||
if self.site_config[server_name] then
|
||||
if self.site_config[server_name]['cdn'] then
|
||||
for _,v in ipairs(self.site_config[server_name]['cdn_header'])
|
||||
local site_config = self.site_config
|
||||
if site_config[server_name] then
|
||||
if site_config[server_name]['cdn'] then
|
||||
local request_header = ngx.req.get_headers()
|
||||
for _,v in ipairs(site_config[server_name]['cdn_header'])
|
||||
do
|
||||
if request_header[v] ~= nil and request_header[v] ~= "" then
|
||||
local header_tmp = request_header[v]
|
||||
if type(header_tmp) == "table" then header_tmp = header_tmp[1] end
|
||||
client_ip = split(header_tmp,',')[1]
|
||||
client_ip = self:split(header_tmp,',')[1]
|
||||
-- return client_ip
|
||||
break;
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if string.match(client_ip,"%d+%.%d+%.%d+%.%d+") == nil or not self:is_ipaddr(client_ip) then
|
||||
|
||||
|
||||
-- ipv6
|
||||
if type(client_ip) == 'table' then client_ip = "" end
|
||||
if client_ip ~= "unknown" and ngx.re.match(client_ip,"^([a-fA-F0-9]*):") then
|
||||
return client_ip
|
||||
end
|
||||
|
||||
-- ipv4
|
||||
if not ngx.re.match(client_ip,"\\d+\\.\\d+\\.\\d+\\.\\d+") == nil or not self:is_ipaddr(client_ip) then
|
||||
client_ip = ngx.var.remote_addr
|
||||
if client_ip == nil then
|
||||
client_ip = "unknown"
|
||||
@@ -408,12 +710,12 @@ end
|
||||
|
||||
|
||||
function _M.is_site_config(self,cname)
|
||||
local server_name = self.params["server_name"]
|
||||
if self.site_config[server_name] ~= nil then
|
||||
local site_config = self.site_config
|
||||
if site_config[server_name] ~= nil then
|
||||
if cname == 'cc' then
|
||||
return self.site_config[server_name][cname]['open']
|
||||
return site_config[server_name][cname]['open']
|
||||
else
|
||||
return self.site_config[server_name][cname]
|
||||
return site_config[server_name][cname]
|
||||
end
|
||||
end
|
||||
return true
|
||||
@@ -434,6 +736,16 @@ function _M.get_boundary(self)
|
||||
end
|
||||
|
||||
|
||||
function _M.is_key(self, arr, key)
|
||||
for _,v in ipairs(arr) do
|
||||
if v == key then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function _M.return_post_data(self)
|
||||
if method ~= "POST" then return false end
|
||||
content_length = tonumber(self.params["request_header"]['content-length'])
|
||||
|
||||
+322
-387
@@ -1,171 +1,167 @@
|
||||
|
||||
local cpath = "{$WAF_PATH}/"
|
||||
local rpath = "{$WAF_PATH}/rule/"
|
||||
local logdir = "{$ROOT_PATH}/wwwlogs/waf/"
|
||||
local json = require "cjson"
|
||||
local ngx_match = ngx.re.find
|
||||
|
||||
local _C = require "common"
|
||||
local C = _C:new(cpath, rpath, logdir)
|
||||
local __WAF = require "common"
|
||||
|
||||
-- print(json.encode(__C))
|
||||
local C = __WAF:getInstance()
|
||||
|
||||
local config = require "waf_config"
|
||||
local site_config = require "waf_site"
|
||||
local config_domains = require "waf_domains"
|
||||
|
||||
-- C:D("config:"..C:to_json(config))
|
||||
|
||||
config = C:read_file_body_decode(cpath .. 'config.json')
|
||||
local site_config = C:read_file_body_decode(cpath .. 'site.json')
|
||||
C:setConfData(config, site_config)
|
||||
C:setDebug(true)
|
||||
|
||||
-- D func
|
||||
local function D(msg)
|
||||
local _msg = ''
|
||||
if type(msg) == 'table' then
|
||||
for key, val in pairs(msg) do
|
||||
_msg = key..':'..val.."\n"
|
||||
end
|
||||
elseif type(msg) == 'string' then
|
||||
_msg = msg
|
||||
elseif type(msg) == 'nil' then
|
||||
_msg = 'nil'
|
||||
else
|
||||
_msg = msg
|
||||
end
|
||||
|
||||
if not debug_mode then return true end
|
||||
local fp = io.open(cpath..'debug.log', 'ab')
|
||||
if fp == nil then
|
||||
return nil
|
||||
end
|
||||
local localtime = os.date("%Y-%m-%d %H:%M:%S")
|
||||
if server_name then
|
||||
fp:write(tostring(_msg) .. "\n")
|
||||
else
|
||||
fp:write(localtime..":"..tostring(_msg) .. "\n")
|
||||
end
|
||||
fp:flush()
|
||||
fp:close()
|
||||
return true
|
||||
end
|
||||
local get_html = require "html_get"
|
||||
local post_html = require "html_post"
|
||||
local other_html = require "html_other"
|
||||
local user_agent_html = require "html_user_agent"
|
||||
local cc_safe_js_html = require "html_safe_js"
|
||||
|
||||
function initParams()
|
||||
local args_rules = require "rule_args"
|
||||
local ip_white_rules = require "rule_ip_white"
|
||||
local ip_black_rules = require "rule_ip_black"
|
||||
local ipv6_black_rules = require "rule_ipv6_black"
|
||||
local scan_black_rules = require "rule_scan_black"
|
||||
local user_agent_rules = require "rule_user_agent"
|
||||
local post_rules = require "rule_post"
|
||||
local cookie_rules = require "rule_cookie"
|
||||
local url_rules = require "rule_url"
|
||||
|
||||
|
||||
local server_name = string.gsub(C:get_sn(config_domains),'_','.')
|
||||
|
||||
local function initParams()
|
||||
local data = {}
|
||||
data['ip'] = C:get_client_ip()
|
||||
data['server_name'] = server_name
|
||||
data['ip'] = C:get_real_ip(server_name)
|
||||
data['ipn'] = C:arrip(data['ip'])
|
||||
data['request_header'] = ngx.req.get_headers()
|
||||
data['uri'] = ngx.unescape_uri(ngx.var.uri)
|
||||
data['server_name'] = string.gsub(C:get_server_name(),'_','.')
|
||||
data['uri_request_args'] = ngx.req.get_uri_args()
|
||||
data['method'] = ngx.req.get_method()
|
||||
data['request_uri'] = ngx.var.request_uri
|
||||
data['status_code'] = ngx.status
|
||||
data['user_agent'] = data['request_header']['user-agent']
|
||||
data['cookie'] = ngx.var.http_cookie
|
||||
data['time'] = ngx.time()
|
||||
return data
|
||||
end
|
||||
|
||||
local params = initParams()
|
||||
C:setParams(params)
|
||||
|
||||
local cpu_percent = ngx.shared.waf_limit:get("cpu_usage")
|
||||
if not cpu_percent then
|
||||
cpu_percent = 0
|
||||
end
|
||||
|
||||
|
||||
function get_return_state(rstate,rmsg)
|
||||
local function get_return_state(rstate,rmsg)
|
||||
result = {}
|
||||
result['status'] = rstate
|
||||
result['msg'] = rmsg
|
||||
return result
|
||||
end
|
||||
|
||||
function get_waf_drop_ip()
|
||||
local data = ngx.shared.drop_ip:get_keys(0)
|
||||
local function get_waf_drop_ip()
|
||||
local data = ngx.shared.waf_drop_ip:get_keys(0)
|
||||
return data
|
||||
end
|
||||
|
||||
local function return_json(status,msg)
|
||||
ngx.header.content_type = "application/json"
|
||||
result = {}
|
||||
result['status'] = status
|
||||
result['msg'] = msg
|
||||
ngx.say(json.encode(data))
|
||||
ngx.exit(200)
|
||||
end
|
||||
|
||||
function is_chekc_table(data,strings)
|
||||
local function is_chekc_table(data,strings)
|
||||
if type(data) ~= 'table' then return 1 end
|
||||
if not data then return 1 end
|
||||
data=chekc_ip_timeout(data)
|
||||
data = chekc_ip_timeout(data)
|
||||
for k,v in pairs(data)
|
||||
do
|
||||
if strings ==v['ip'] then
|
||||
if strings == v['ip'] then
|
||||
return 3
|
||||
end
|
||||
end
|
||||
return 2
|
||||
end
|
||||
|
||||
function save_ip_on(data)
|
||||
locak_file=read_file_body(cpath2 .. 'stop_ip.lock')
|
||||
if not locak_file then
|
||||
C:write_file(cpath2 .. 'stop_ip.lock','1')
|
||||
local function remove_waf_drop_ip()
|
||||
ngx.header.content_type = "application/json"
|
||||
local ip = params['uri_request_args']['ip']
|
||||
|
||||
if not ip or not C:is_ipaddr(ip) then
|
||||
local data = get_return_state(-1, "格式错误")
|
||||
ngx.say(json.encode(data))
|
||||
ngx.exit(200)
|
||||
return true
|
||||
end
|
||||
name='stop_ip'
|
||||
local extime=18000
|
||||
data=json.encode(data)
|
||||
ngx.shared.btwaf:set(cpath2 .. name,data,extime)
|
||||
if not ngx.shared.btwaf:get(cpath2 .. name .. '_lock') then
|
||||
ngx.shared.btwaf:set(cpath2 .. name .. '_lock',1,0.5)
|
||||
C:write_file(cpath2 .. name .. '.json',data)
|
||||
|
||||
local sign = "remove_waf_drop_ip"
|
||||
if C:is_working(sign) then
|
||||
local data = get_return_state(-1, "fail")
|
||||
ngx.say(json.encode(data))
|
||||
ngx.exit(200)
|
||||
return true
|
||||
end
|
||||
|
||||
C:lock_working(sign)
|
||||
ngx.shared.waf_drop_ip:delete(ip)
|
||||
C:unlock_working(sign)
|
||||
|
||||
local data = get_return_state(0, "ok")
|
||||
ngx.say(json.encode(data))
|
||||
ngx.exit(200)
|
||||
end
|
||||
|
||||
function remove_btwaf_drop_ip()
|
||||
if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end
|
||||
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
|
||||
ret=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
|
||||
ip_data=json.decode(ret)
|
||||
result=is_chekc_table(ip_data,uri_request_args['ip'])
|
||||
os.execute("sleep " .. 0.6)
|
||||
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
|
||||
ip_data2=json.decode(ret2)
|
||||
if result == 3 then
|
||||
for k,v in pairs(ip_data2)
|
||||
do
|
||||
if uri_request_args['ip'] == v['ip'] then
|
||||
v['time']=0
|
||||
end
|
||||
end
|
||||
end
|
||||
save_ip_on(ip_data2)
|
||||
local function clean_waf_drop_ip()
|
||||
ngx.header.content_type = "application/json"
|
||||
|
||||
local sign = "clean_waf_drop_ip"
|
||||
if C:is_working(sign) then
|
||||
local data = get_return_state(-1, "fail")
|
||||
ngx.say(json.encode(data))
|
||||
ngx.exit(200)
|
||||
return true
|
||||
end
|
||||
ngx.shared.drop_ip:delete(uri_request_args['ip'])
|
||||
return get_return_state(true,uri_request_args['ip'] .. '已解封')
|
||||
|
||||
C:lock_working(sign)
|
||||
ngx.shared.waf_drop_ip:flush_all()
|
||||
C:unlock_working(sign)
|
||||
|
||||
local data = get_return_state(0, "ok")
|
||||
ngx.say(json.encode(data))
|
||||
ngx.exit(200)
|
||||
end
|
||||
|
||||
function clean_btwaf_drop_ip()
|
||||
if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then
|
||||
ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip')
|
||||
ip_data2=json.decode(ret2)
|
||||
for k,v in pairs(ip_data2)
|
||||
do
|
||||
v['time']=0
|
||||
end
|
||||
save_ip_on(ip_data2)
|
||||
os.execute("sleep " .. 2)
|
||||
end
|
||||
local data = get_btwaf_drop_ip()
|
||||
for _,value in ipairs(data)
|
||||
do
|
||||
ngx.shared.drop_ip:delete(value)
|
||||
end
|
||||
return get_return_state(true,'已解封所有封锁IP')
|
||||
end
|
||||
|
||||
function min_route()
|
||||
local function min_route()
|
||||
if ngx.var.remote_addr ~= '127.0.0.1' then return false end
|
||||
local uri = params['uri']
|
||||
if uri == '/get_waf_drop_ip' then
|
||||
return_message(200,get_waf_drop_ip())
|
||||
ngx.header.content_type = "application/json"
|
||||
local data = get_return_state(0, get_waf_drop_ip())
|
||||
ngx.say(json.encode(data))
|
||||
ngx.exit(200)
|
||||
elseif uri == '/remove_waf_drop_ip' then
|
||||
return_message(200,remove_waf_drop_ip())
|
||||
remove_waf_drop_ip()
|
||||
elseif uri == '/clean_waf_drop_ip' then
|
||||
return_message(200,clean_waf_drop_ip())
|
||||
clean_waf_drop_ip()
|
||||
end
|
||||
end
|
||||
|
||||
local get_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["get"]["reqfile"])
|
||||
local post_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["post"]["reqfile"])
|
||||
local user_agent_html = C:read_file_body(config["reqfile_path"] .. '/' .. config["user-agent"]["reqfile"])
|
||||
local args_rules = C:read_file_table('args')
|
||||
local ip_white_rules = C:read_file('ip_white')
|
||||
local ip_black_rules = C:read_file('ip_black')
|
||||
local scan_black_rules = C:read_file('scan_black')
|
||||
|
||||
function waf_args()
|
||||
local function waf_get_args()
|
||||
if not config['get']['open'] or not C:is_site_config('get') then return false end
|
||||
if C:is_ngx_match(args_rules, params['uri_request_args'],'args') then
|
||||
-- C:D("waf_get_args:"..C:to_json(args_rules)..":"..json.encode(params['uri_request_args']))
|
||||
if C:ngx_match_list(args_rules, params['uri_request_args']) then
|
||||
C:write_log('args','regular')
|
||||
C:return_html(config['get']['status'], get_html)
|
||||
return true
|
||||
@@ -174,7 +170,7 @@ function waf_args()
|
||||
end
|
||||
|
||||
|
||||
function waf_ip_white()
|
||||
local function waf_ip_white()
|
||||
for _,rule in ipairs(ip_white_rules)
|
||||
do
|
||||
if C:compare_ip(rule) then
|
||||
@@ -184,7 +180,8 @@ function waf_ip_white()
|
||||
return false
|
||||
end
|
||||
|
||||
function waf_ip_black()
|
||||
local function waf_ip_black()
|
||||
-- ipv4 ip black
|
||||
for _,rule in ipairs(ip_black_rules)
|
||||
do
|
||||
if C:compare_ip(rule) then
|
||||
@@ -192,115 +189,198 @@ function waf_ip_black()
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
-- ipv6 ip black
|
||||
for _,rule in ipairs(ipv6_black_rules)
|
||||
do
|
||||
if rule == params['ip'] then
|
||||
ngx.exit(config['cc']['status'])
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function waf_drop()
|
||||
local count,_ = ngx.shared.drop_ip:get(ip)
|
||||
local function waf_user_agent()
|
||||
-- user_agent 过滤
|
||||
-- if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
|
||||
|
||||
-- C:D("waf_user_agent;user_agent_rules:"..json.encode(user_agent_rules)..",ua:"..tostring(params['request_header']['user-agent']))
|
||||
if C:is_ngx_match_ua(user_agent_rules, params['request_header']['user-agent']) then
|
||||
-- C:D("waf_user_agent........... true")
|
||||
C:write_log('user_agent','regular')
|
||||
C:return_html(config['user-agent']['status'], user_agent_html)
|
||||
return true
|
||||
end
|
||||
|
||||
-- C:D("waf_user_agent........... false")
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
local function waf_drop_ip()
|
||||
local ip = params['ip']
|
||||
local count = ngx.shared.waf_drop_ip:get(ip)
|
||||
if not count then return false end
|
||||
if count > config['retry'] then
|
||||
|
||||
local retry = config['retry']['retry']
|
||||
-- C:D("waf_drop;count:"..tostring(count)..",retry:"..tostring(retry))
|
||||
-- C:D("waf_drop;count > retry:"..tostring(count > retry))
|
||||
if count > retry then
|
||||
-- C:D("waf_drop_ip........... true")
|
||||
ngx.exit(config['cc']['status'])
|
||||
return true
|
||||
end
|
||||
-- C:D("waf_drop_ip........... false")
|
||||
return false
|
||||
end
|
||||
|
||||
local function waf_cc()
|
||||
if not config['cc']['open'] or not C:is_site_config('cc') then return false end
|
||||
|
||||
function waf_user_agent()
|
||||
if not config['user-agent']['open'] or not C:is_site_config('user-agent') then return false end
|
||||
if C:is_ngx_match(user_agent_rules,params['request_header']['user-agent'],'user_agent') then
|
||||
C:write_log('user_agent','regular')
|
||||
C:return_html(config['user-agent']['status'],user_agent_html)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function cc()
|
||||
local ip = params['ip']
|
||||
local request_uri = params['request_uri']
|
||||
local endtime = config['cc']['endtime']
|
||||
|
||||
if not config['cc']['open'] or not site_cc then return false end
|
||||
-- 多次cc,才封禁。
|
||||
-- local ip_lock = ngx.shared.waf_drop_ip:get(ip)
|
||||
-- if ip_lock then
|
||||
-- if ip_lock > 0 then
|
||||
-- ngx.exit(config['cc']['status'])
|
||||
-- return true
|
||||
-- end
|
||||
-- end
|
||||
|
||||
local request_uri = params['request_uri']
|
||||
|
||||
local token = ngx.md5(ip .. '_' .. request_uri)
|
||||
local count,_ = ngx.shared.limit:get(token)
|
||||
local count = ngx.shared.waf_limit:get(token)
|
||||
|
||||
local endtime = config['cc']['endtime']
|
||||
local waf_limit = config['cc']['limit']
|
||||
local cycle = config['cc']['cycle']
|
||||
|
||||
if count then
|
||||
if count > limit then
|
||||
local safe_count,_ = ngx.shared.drop_sum:get(ip)
|
||||
if count > waf_limit then
|
||||
|
||||
local safe_count, _ = ngx.shared.waf_drop_sum:get(ip)
|
||||
if not safe_count then
|
||||
ngx.shared.drop_sum:set(ip,1,86400)
|
||||
ngx.shared.waf_drop_sum:set(ip, 1, 86400)
|
||||
safe_count = 1
|
||||
else
|
||||
ngx.shared.drop_sum:incr(ip,1)
|
||||
ngx.shared.waf_drop_sum:incr(ip, 1)
|
||||
end
|
||||
local lock_time = (endtime * safe_count)
|
||||
if lock_time > 86400 then lock_time = 86400 end
|
||||
ngx.shared.drop_ip:set(ip,retry+1,lock_time)
|
||||
C:write_log('cc',cycle..'秒内累计超过'..limit..'次请求,封锁' .. lock_time .. '秒')
|
||||
C:write_drop_ip('cc',lock_time)
|
||||
if not server_name then
|
||||
insert_ip_list(ip,lock_time,os.time(),'1111')
|
||||
else
|
||||
insert_ip_list(ip,lock_time,os.time(),server_name)
|
||||
end
|
||||
|
||||
|
||||
ngx.shared.waf_drop_ip:set(ip, 1, lock_time)
|
||||
local reason = cycle..'秒内累计超过'..waf_limit..'次请求,封锁' .. lock_time .. '秒'
|
||||
C:write_log('cc', reason)
|
||||
C:log(params, 'cc',reason)
|
||||
ngx.exit(config['cc']['status'])
|
||||
return true
|
||||
else
|
||||
ngx.shared.limit:incr(token,1)
|
||||
ngx.shared.waf_limit:incr(token, 1)
|
||||
end
|
||||
else
|
||||
ngx.shared.limit:set(token,1,cycle)
|
||||
ngx.shared.waf_drop_sum:set(ip, 1, 86400)
|
||||
ngx.shared.waf_limit:set(token, 1, cycle)
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- 是否符合开强制验证条件
|
||||
local function is_open_waf_cc_increase()
|
||||
|
||||
if config['safe_verify']['open'] then
|
||||
return true
|
||||
end
|
||||
|
||||
if site_config[server_name]['safe_verify']['open'] then
|
||||
return true
|
||||
end
|
||||
|
||||
if cpu_percent >= config['safe_verify']['cpu'] then
|
||||
return true
|
||||
end
|
||||
|
||||
if cpu_percent >= site_config[server_name]['safe_verify']['cpu'] then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
--强制验证是否使用正常浏览器访问网站
|
||||
function waf_cc_increase()
|
||||
|
||||
if not config['cc']['open'] or not site_cc then return false end
|
||||
if not site_config[server_name] then return false end
|
||||
if not site_config[server_name]['cc']['increase'] then return false end
|
||||
local function waf_cc_increase()
|
||||
if not is_open_waf_cc_increase() then return false end
|
||||
|
||||
local ip = params['ip']
|
||||
local uri = params['uri']
|
||||
local cache_token = ngx.md5(ip .. '_' .. server_name)
|
||||
|
||||
--判断是否已经通过验证
|
||||
if ngx.shared.btwaf:get(cache_token) then return false end
|
||||
if cc_uri_white() then
|
||||
ngx.shared.btwaf:delete(cache_token .. '_key')
|
||||
ngx.shared.btwaf:set(cache_token,1,60)
|
||||
return false
|
||||
if ngx.shared.waf_limit:get(cache_token) then return false end
|
||||
|
||||
local cache_rand_key = ip..':rand'
|
||||
local cache_rand = ngx.shared.waf_limit:get(cache_rand_key)
|
||||
if not cache_rand then
|
||||
cache_rand = C:get_random(8)
|
||||
ngx.shared.waf_limit:set(cache_rand_key,cache_rand,30)
|
||||
end
|
||||
if security_verification() then return false end
|
||||
send_check_heml(cache_token)
|
||||
|
||||
local make_token = "waf_unbind_"..cache_rand.."_"..cache_token
|
||||
local make_uri_str = "?token="..make_token
|
||||
local make_uri = "/"..make_uri_str
|
||||
|
||||
if params['uri_request_args']['token'] then
|
||||
local args_token = params['uri_request_args']['token']
|
||||
if args_token == make_token then
|
||||
ngx.shared.waf_limit:set(cache_token, 1, config['safe_verify']['time'])
|
||||
local data = get_return_state(0, "ok")
|
||||
ngx.say(json.encode(data))
|
||||
ngx.exit(200)
|
||||
end
|
||||
end
|
||||
|
||||
local cc_html = ngx.re.gsub(cc_safe_js_html, "{uri}", make_uri_str)
|
||||
C:return_html(200, cc_html)
|
||||
end
|
||||
|
||||
|
||||
function waf_url()
|
||||
local function waf_url()
|
||||
if not config['get']['open'] or not C:is_site_config('get') then return false end
|
||||
--正则--
|
||||
if C:is_ngx_match(url_rules,params["uri"],'url') then
|
||||
-- C:D("waf_url:"..json.encode(url_rules)..":uri:"..params["uri"])
|
||||
if C:ngx_match_list(url_rules, params["uri"]) then
|
||||
C:write_log('url','regular')
|
||||
C:return_html(config['get']['status'],get_html)
|
||||
C:return_html(config['get']['status'], get_html)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function waf_scan_black()
|
||||
local function waf_scan_black()
|
||||
-- 扫描软件禁止
|
||||
if not config['scan']['open'] or not C:is_site_config('scan') then return false end
|
||||
if C:is_ngx_match(scan_black_rules['cookie'],params["request_header"]["cookie"],false) then
|
||||
C:write_log('scan','regular')
|
||||
ngx.exit(config['scan']['status'])
|
||||
return true
|
||||
end
|
||||
if C:is_ngx_match(scan_black_rules['args'],params["request_uri"],false) then
|
||||
if not params["cookie"] then
|
||||
if C:ngx_match_string(scan_black_rules['cookie'], tostring(params["cookie"]),'scan') then
|
||||
C:write_log('scan','regular')
|
||||
ngx.exit(config['scan']['status'])
|
||||
return true
|
||||
end
|
||||
end
|
||||
|
||||
if C:ngx_match_string(scan_black_rules['args'], params["request_uri"], 'scan') then
|
||||
C:write_log('scan','regular')
|
||||
ngx.exit(config['scan']['status'])
|
||||
return true
|
||||
end
|
||||
|
||||
for key,value in pairs(params["request_header"])
|
||||
do
|
||||
if C:is_ngx_match(scan_black_rules['header'], key, false) then
|
||||
if C:ngx_match_string(scan_black_rules['header'], key, 'scan') then
|
||||
C:write_log('scan','regular')
|
||||
ngx.exit(config['scan']['status'])
|
||||
return true
|
||||
@@ -309,253 +389,120 @@ function waf_scan_black()
|
||||
return false
|
||||
end
|
||||
|
||||
function waf_post_referer()
|
||||
if params['method'] ~= "POST" then return false end
|
||||
if C:is_ngx_match(referer_local, params['request_header']['Referer'],'post') then
|
||||
C:write_log('post_referer','regular')
|
||||
C:return_html(config['post']['status'],post_html)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function waf_post()
|
||||
local function waf_post()
|
||||
if not config['post']['open'] or not C:is_site_config('post') then return false end
|
||||
if params['method'] ~= "POST" then return false end
|
||||
if waf_post_referer() then return true end
|
||||
content_length = tonumber(params["request_header"]['content-length'])
|
||||
max_len = 640 * 1020000
|
||||
local content_length = tonumber(params["request_header"]['content-length'])
|
||||
local max_len = 640 * 1020000
|
||||
if content_length > max_len then return false end
|
||||
if C:get_boundary() then return false end
|
||||
ngx.req.read_body()
|
||||
request_args = ngx.req.get_post_args()
|
||||
if not request_args then
|
||||
return false
|
||||
|
||||
local request_args = params['uri_request_args']
|
||||
if not request_args then return false end
|
||||
|
||||
for key, val in pairs(request_args) do
|
||||
if type(val) == "table" then
|
||||
if type(val[1]) == "boolean" then
|
||||
return false
|
||||
end
|
||||
data = table.concat(val, ", ")
|
||||
else
|
||||
data = val
|
||||
end
|
||||
end
|
||||
|
||||
if C:is_ngx_match(post_rules,request_args,'post') then
|
||||
-- C:D("post:"..json.encode(data))
|
||||
if C:ngx_match_list(post_rules, data) then
|
||||
C:write_log('post','regular')
|
||||
C:return_html(config['post']['status'],post_html)
|
||||
C:return_html(config['post']['status'], post_html)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function X_Forwarded()
|
||||
|
||||
function post_data_chekc()
|
||||
if params['method'] =="POST" then
|
||||
if C:return_post_data() then return false end
|
||||
ngx.req.read_body()
|
||||
request_args = ngx.req.get_post_args()
|
||||
if not request_args then return false end
|
||||
|
||||
if request_header then
|
||||
if not request_header['Content-Type'] then return false end
|
||||
av = string.match(request_header['Content-Type'],"=.+")
|
||||
end
|
||||
|
||||
if not av then return false end
|
||||
ac = split(av,'=')
|
||||
|
||||
if not ac then return false end
|
||||
|
||||
list_list=nil
|
||||
for i,v in ipairs(ac)
|
||||
do
|
||||
list_list='--'..v
|
||||
end
|
||||
|
||||
if not list_list then return false end
|
||||
aaa=nil
|
||||
for k,v in pairs(request_args)
|
||||
do
|
||||
aaa=v
|
||||
end
|
||||
|
||||
if not aaa then return false end
|
||||
if tostring(aaa) == 'true' then return false end
|
||||
if type(aaa) ~= "string" then return false end
|
||||
data_len=split(aaa,list_list)
|
||||
|
||||
--return return_message(200,data_len)
|
||||
if not data_len then return false end
|
||||
if arrlen(data_len) ==0 then return false end
|
||||
|
||||
if C:is_ngx_match(post_rules,data_len,'post') then
|
||||
C:write_log('post','regular')
|
||||
C:return_html(config['post']['status'],post_html)
|
||||
return true
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function X_Forwarded()
|
||||
if params['method'] ~= "GET" then return false end
|
||||
if not config['get']['open'] or not C:is_site_config('get') then return false end
|
||||
if C:is_ngx_match(args_rules,params["request_header"]['X-forwarded-For'],'args') then
|
||||
if not params["request_header"]['X-forwarded-For'] then return false end
|
||||
|
||||
if C:ngx_match_list(args_rules, params["request_header"]['X-forwarded-For']) then
|
||||
C:write_log('args','regular')
|
||||
C:return_html(config['get']['status'],get_html)
|
||||
C:return_html(config['get']['status'], get_html)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function post_X_Forwarded()
|
||||
local function post_X_Forwarded()
|
||||
if not config['post']['open'] or not C:is_site_config('post') then return false end
|
||||
if params['method'] ~= "POST" then return false end
|
||||
if C:is_ngx_match(post_rules,params["request_header"]['X-forwarded-For'],'post') then
|
||||
if not params["request_header"]['X-forwarded-For'] then return false end
|
||||
if C:is_ngx_match_list(post_rules, params["request_header"]['X-forwarded-For']) then
|
||||
C:write_log('post','regular')
|
||||
C:return_html(config['post']['status'],post_html)
|
||||
C:return_html(config['post']['status'], post_html)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function php_path()
|
||||
if site_config[server_name] == nil then return false end
|
||||
for _,rule in ipairs(site_config[server_name]['disable_php_path'])
|
||||
do
|
||||
if ngx_match(uri,rule .. "/?.*\\.php$","isjo") then
|
||||
C:write_log('php_path','regular')
|
||||
C:return_html(config['other']['status'],other_html)
|
||||
return C:return_message(200,uri)
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function url_path()
|
||||
if site_config[server_name] == nil then return false end
|
||||
for _,rule in ipairs(site_config[server_name]['disable_path'])
|
||||
do
|
||||
if ngx_match(uri,rule,"isjo") then
|
||||
C:write_log('path','regular')
|
||||
C:return_html(config['other']['status'],other_html)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function url_ext()
|
||||
local function url_ext()
|
||||
if site_config[server_name] == nil then return false end
|
||||
for _,rule in ipairs(site_config[server_name]['disable_ext'])
|
||||
do
|
||||
if ngx_match(uri,"\\."..rule.."$","isjo") then
|
||||
C:write_log('url_ext','regular')
|
||||
C:return_html(config['other']['status'],other_html)
|
||||
if C:ngx_match_string("\\."..rule.."$", params['uri'],'url_ext') then
|
||||
if rule == "php" then
|
||||
C:write_log('php_path','regular')
|
||||
else
|
||||
C:write_log('path','regular')
|
||||
end
|
||||
C:return_html(config['other']['status'], other_html)
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function url_rule_ex()
|
||||
if site_config[server_name] == nil then return false end
|
||||
if method == "POST" and not request_args then
|
||||
content_length=tonumber(request_header['content-length'])
|
||||
max_len = 640 * 102400000
|
||||
request_args = nil
|
||||
if content_length < max_len then
|
||||
ngx.req.read_body()
|
||||
request_args = ngx.req.get_post_args()
|
||||
end
|
||||
end
|
||||
for _,rule in ipairs(site_config[server_name]['url_rule'])
|
||||
do
|
||||
if ngx_match(uri,rule[1],"isjo") then
|
||||
if C:is_ngx_match(rule[2],uri_request_args,false) then
|
||||
C:write_log('url_rule','regular')
|
||||
C:return_html(config['other']['status'],other_html)
|
||||
return true
|
||||
end
|
||||
|
||||
if params['method'] == "POST" and request_args ~= nil then
|
||||
if C:is_ngx_match(rule[2],request_args,'post') then
|
||||
C:write_log('post','regular')
|
||||
C:return_html(config['other']['status'],other_html)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function url_tell()
|
||||
if site_config[server_name] == nil then return false end
|
||||
for _,rule in ipairs(site_config[server_name]['url_tell'])
|
||||
do
|
||||
if ngx_match(uri,rule[1],"isjo") then
|
||||
if uri_request_args[rule[2]] ~= rule[3] then
|
||||
C:write_log('url_tell','regular')
|
||||
C:return_html(config['other']['status'],other_html)
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function disable_upload_ext(ext)
|
||||
local function disable_upload_ext(ext)
|
||||
if not ext then return false end
|
||||
ext = string.lower(ext)
|
||||
if is_key(site_config[server_name]['disable_upload_ext'],ext) then
|
||||
C:write_log('upload_ext','上传扩展名黑名单')
|
||||
if C:is_key(site_config[server_name]['disable_upload_ext'], ext) then
|
||||
C:write_log('upload_ext', '上传扩展名黑名单')
|
||||
C:return_html(config['other']['status'],other_html)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function data_in_php(data)
|
||||
if not data then
|
||||
return false
|
||||
else
|
||||
if C:is_ngx_match('php',data,'post') then
|
||||
C:write_log('upload_ext','上传扩展名黑名单')
|
||||
C:return_html(config['other']['status'],other_html)
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function post_data()
|
||||
local function post_data()
|
||||
if params["method"] ~= "POST" then return false end
|
||||
content_length = tonumber(params["request_header"]['content-length'])
|
||||
-- C:D("content-length:"..params["request_header"]['content-length'])
|
||||
local content_length = tonumber(params["request_header"]['content-length'])
|
||||
if not content_length then return false end
|
||||
max_len = 2560 * 1024000
|
||||
local max_len = 2560 * 1024000
|
||||
if content_length > max_len then return false end
|
||||
local boundary = C:get_boundary()
|
||||
-- C:D("boundary:".. tostring( boundary) )
|
||||
if boundary then
|
||||
ngx.req.read_body()
|
||||
local data = ngx.req.get_body_data()
|
||||
if not data then return false end
|
||||
local tmp = ngx.re.match(data,[[filename=\"(.+)\.(.*)\"]])
|
||||
if not tmp then return false end
|
||||
if not tmp[2] then return false end
|
||||
local tmp2=ngx.re.match(ngx.req.get_body_data(),[[Content-Type:[^\+]{45}]])
|
||||
--return return_message(200,tmp2[0])
|
||||
if not tmp or not tmp[2] then return false end
|
||||
-- C:D("upload_ext:".. tostring(tmp[2]) )
|
||||
disable_upload_ext(tmp[2])
|
||||
if tmp2 == nil then return false end
|
||||
data_in_php(tmp2[0])
|
||||
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function waf_cookie()
|
||||
local function waf_cookie()
|
||||
if not config['cookie']['open'] or not C:is_site_config('cookie') then return false end
|
||||
if not params["request_header"]['cookie'] then return false end
|
||||
if type(params["request_header"]['cookie']) ~= "string" then return false end
|
||||
request_cookie = string.lower(params["request_header"]['cookie'])
|
||||
if C:is_ngx_match(cookie_rules,request_cookie,'cookie') then
|
||||
if C:ngx_match_list(cookie_rules,request_cookie,'cookie') then
|
||||
C:write_log('cookie','regular')
|
||||
C:return_html(config['cookie']['status'],cookie_html)
|
||||
return true
|
||||
@@ -563,55 +510,43 @@ function waf_cookie()
|
||||
return false
|
||||
end
|
||||
|
||||
function waf_referer()
|
||||
if params["method"] ~= "GET" then return false end
|
||||
if not config['get']['open'] or not C:is_site_config('get') then return false end
|
||||
if C:is_ngx_match(referer_local,params["request_header"]['Referer'],'args') then
|
||||
C:write_log('get_referer','regular')
|
||||
C:return_html(config['get']['status'], get_html)
|
||||
return true
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function waf()
|
||||
min_route()
|
||||
|
||||
-- white ip
|
||||
if waf_ip_white() then return true end
|
||||
waf_ip_black()
|
||||
|
||||
-- black ip
|
||||
if waf_ip_black() then return true end
|
||||
|
||||
waf_drop()
|
||||
waf_user_agent()
|
||||
-- 封禁ip返回
|
||||
if waf_drop_ip() then return true end
|
||||
|
||||
waf_url()
|
||||
-- ua check
|
||||
if waf_user_agent() then return true end
|
||||
if waf_url() then return true end
|
||||
|
||||
if params["method"] == "GET" then
|
||||
waf_referer()
|
||||
waf_cookie()
|
||||
end
|
||||
-- cc setting
|
||||
if waf_cc_increase() then return true end
|
||||
if waf_cc() then return true end
|
||||
|
||||
if params["method"] == "POST" then
|
||||
waf_referer()
|
||||
waf_cookie()
|
||||
end
|
||||
-- cookie检查
|
||||
if waf_cookie() then return true end
|
||||
|
||||
-- args参数拦截
|
||||
if waf_get_args() then return true end
|
||||
|
||||
waf_args()
|
||||
waf_scan_black()
|
||||
-- 扫描软件禁止
|
||||
if waf_scan_black() then return true end
|
||||
|
||||
waf_post()
|
||||
post_data_chekc()
|
||||
|
||||
local server_name = params["server_name"]
|
||||
if site_config[server_name] then
|
||||
X_Forwarded()
|
||||
post_X_Forwarded()
|
||||
php_path()
|
||||
url_path()
|
||||
url_ext()
|
||||
url_rule_ex()
|
||||
url_tell()
|
||||
post_data()
|
||||
if waf_post() then return true end
|
||||
|
||||
if site_config[server_name] and site_config[server_name]['open'] then
|
||||
if X_Forwarded() then return true end
|
||||
if post_X_Forwarded() then return true end
|
||||
if url_ext() then return true end
|
||||
if post_data() then return true end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -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 +0,0 @@
|
||||
waf()
|
||||
@@ -1 +1 @@
|
||||
[[1, "(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)", "\u5173\u952e\u8bcd\u8fc7\u6ee41", 0]]
|
||||
[[1,"(HTTrack|Apache-HttpClient|harvest|audit|dirbuster|pangolin|nmap|sqln|hydra|Parser|libwww|BBBike|sqlmap|w3af|owasp|Nikto|fimap|havij|zmeu|BabyKrokodil|netsparker|httperf| SF/)","关键词过滤1",0],[1,"(ApacheBench)","AB测试",0]]
|
||||
@@ -1 +1 @@
|
||||
{"rules":{"user_agent":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0}
|
||||
{"rules":{"path":0,"php_path":0,"upload_ext":0,"user_agent":0,"scan":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0}
|
||||
@@ -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 +0,0 @@
|
||||
10.0.68.75
|
||||
@@ -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)\[
|
||||
@@ -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
|
||||
@@ -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)\=
|
||||
@@ -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>
|
||||
|
||||
@@ -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 +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/)
|
||||
@@ -1,2 +0,0 @@
|
||||
127.0.0.1
|
||||
^192\.168\.
|
||||
@@ -64,6 +64,9 @@ Install_openresty()
|
||||
--with-http_slice_module \
|
||||
--with-http_stub_status_module \
|
||||
--with-http_realip_module
|
||||
# --without-luajit-gc64
|
||||
# --with-debug
|
||||
# 用于调式
|
||||
|
||||
make -j${cpuCore} && make install && make clean
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ group = {$PHP_GROUP}
|
||||
listen = /run/php/php{$PHP_VERSION}-fpm.sock
|
||||
listen.owner = {$PHP_USER}
|
||||
listen.group = {$PHP_GROUP}
|
||||
listen.backlog = 4096
|
||||
pm = dynamic
|
||||
pm.max_children = 50
|
||||
pm.start_servers = 5
|
||||
|
||||
@@ -1,3 +1,41 @@
|
||||
|
||||
<style type="text/css">
|
||||
.bt-w-main{
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.session_clear_list {
|
||||
border:1px solid #ececec;
|
||||
margin-bottom: 15px;
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.session_clear_list .line {
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #ececec;
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.session_clear_list .line:last-child {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.session_clear_list .line span{
|
||||
width: auto;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
text-align: left;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.session_clear_list .line span:first-child {
|
||||
width: 170px;
|
||||
border-right: 1px solid #ececec;
|
||||
background: #f7f7f7;
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="bt-form">
|
||||
<div class='plugin_version'></div>
|
||||
<div class="bt-w-main">
|
||||
@@ -13,6 +51,7 @@
|
||||
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
|
||||
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
|
||||
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
|
||||
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
|
||||
<p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
|
||||
<p onclick="pluginLogs('php-apt',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
|
||||
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>
|
||||
|
||||
@@ -490,6 +490,180 @@ def getFpmStatus(version):
|
||||
return mw.returnJson(True, "OK", data)
|
||||
|
||||
|
||||
def getSessionConf(version):
|
||||
filename = getConf(version)
|
||||
if not os.path.exists(filename):
|
||||
return mw.returnJson(False, '指定PHP版本不存在!')
|
||||
|
||||
phpini = mw.readFile(filename)
|
||||
|
||||
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
|
||||
save_handler = re.search(rep, phpini)
|
||||
if save_handler:
|
||||
save_handler = save_handler.group(1)
|
||||
else:
|
||||
save_handler = "files"
|
||||
|
||||
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
|
||||
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
|
||||
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
|
||||
save_path = re.search(reppath, phpini)
|
||||
if not save_path:
|
||||
save_path = re.search(memcached, phpini)
|
||||
passwd = re.search(passrep, phpini)
|
||||
port = ""
|
||||
if passwd:
|
||||
passwd = passwd.group(1)
|
||||
else:
|
||||
passwd = ""
|
||||
if save_path:
|
||||
port = save_path.group(2)
|
||||
save_path = save_path.group(1)
|
||||
|
||||
else:
|
||||
save_path = ""
|
||||
|
||||
data = {"save_handler": save_handler, "save_path": save_path,
|
||||
"passwd": passwd, "port": port}
|
||||
return mw.returnJson(True, 'ok', data)
|
||||
|
||||
|
||||
def setSessionConf(version):
|
||||
|
||||
args = getArgs()
|
||||
|
||||
ip = args['ip']
|
||||
port = args['port']
|
||||
passwd = args['passwd']
|
||||
save_handler = args['save_handler']
|
||||
|
||||
if save_handler != "file":
|
||||
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
|
||||
if not re.search(iprep, ip):
|
||||
return mw.returnJson(False, '请输入正确的IP地址')
|
||||
|
||||
try:
|
||||
port = int(port)
|
||||
if port >= 65535 or port < 1:
|
||||
return mw.returnJson(False, '请输入正确的端口号')
|
||||
except:
|
||||
return mw.returnJson(False, '请输入正确的端口号')
|
||||
prep = r"[\~\`\/\=]"
|
||||
if re.search(prep, passwd):
|
||||
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
|
||||
|
||||
filename = getConf(version)
|
||||
if not os.path.exists(filename):
|
||||
return mw.returnJson(False, '指定PHP版本不存在!')
|
||||
phpini = mw.readFile(filename)
|
||||
|
||||
session_tmp = getServerDir() + "/tmp/session"
|
||||
|
||||
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
|
||||
val = r'session.save_handler = ' + save_handler + '\n'
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
|
||||
content = mw.execShell(
|
||||
'cat /etc/php/' + version + '/fpm/conf.d/*' + " | grep -v '^;' |tr -s '\n'")
|
||||
content = content[0]
|
||||
|
||||
if save_handler == "memcached":
|
||||
if not re.search("memcached.so", phpini):
|
||||
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
|
||||
if re.search(rep, phpini):
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
|
||||
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
|
||||
|
||||
if save_handler == "memcache":
|
||||
if not content.find('memcache') > -1:
|
||||
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
|
||||
if re.search(rep, phpini):
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
|
||||
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
|
||||
|
||||
if save_handler == "redis":
|
||||
if not content.find('redis') > -1:
|
||||
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
|
||||
if passwd:
|
||||
passwd = "?auth=" + passwd
|
||||
else:
|
||||
passwd = ""
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
|
||||
res = re.search(rep, phpini)
|
||||
if res:
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
|
||||
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
|
||||
|
||||
if save_handler == "file":
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "' + session_tmp + '"\n'
|
||||
if re.search(rep, phpini):
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "' + "/var/lib/php/sessions" + '"',
|
||||
'\n;session.save_path = "' + "/var/lib/php/sessions" + '"' + val, phpini)
|
||||
|
||||
mw.writeFile(filename, phpini)
|
||||
reload(version)
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def getSessionCount_Origin(version):
|
||||
session_tmp = getServerDir() + "/tmp/session"
|
||||
d = ["/tmp", "/var/lib/php/sessions", session_tmp]
|
||||
count = 0
|
||||
for i in d:
|
||||
if not os.path.exists(i):
|
||||
mw.execShell('mkdir -p %s' % i)
|
||||
list = os.listdir(i)
|
||||
for l in list:
|
||||
if os.path.isdir(i + "/" + l):
|
||||
l1 = os.listdir(i + "/" + l)
|
||||
for ll in l1:
|
||||
if "sess_" in ll:
|
||||
count += 1
|
||||
continue
|
||||
if "sess_" in l:
|
||||
count += 1
|
||||
|
||||
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
|
||||
old_file = int(mw.execShell(s)[0].split("\n")[0])
|
||||
|
||||
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
|
||||
old_file += int(mw.execShell(s)[0].split("\n")[0])
|
||||
return {"total": count, "oldfile": old_file}
|
||||
|
||||
|
||||
def getSessionCount(version):
|
||||
data = getSessionCount_Origin(version)
|
||||
return mw.returnJson(True, 'ok!', data)
|
||||
|
||||
|
||||
def cleanSessionOld(version):
|
||||
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
|
||||
mw.execShell(s)
|
||||
|
||||
session_tmp = getServerDir() + "/tmp/session"
|
||||
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
|
||||
mw.execShell(s)
|
||||
old_file_conf = getSessionCount_Origin(version)["oldfile"]
|
||||
if old_file_conf == 0:
|
||||
return mw.returnJson(True, '清理成功')
|
||||
else:
|
||||
return mw.returnJson(True, '清理失败')
|
||||
|
||||
|
||||
def getDisableFunc(version):
|
||||
filename = getConf(version)
|
||||
if not os.path.exists(filename):
|
||||
@@ -688,6 +862,14 @@ if __name__ == "__main__":
|
||||
print(setFpmConfig(version))
|
||||
elif func == 'get_fpm_status':
|
||||
print(getFpmStatus(version))
|
||||
elif func == 'get_session_conf':
|
||||
print(getSessionConf(version))
|
||||
elif func == 'set_session_conf':
|
||||
print(setSessionConf(version))
|
||||
elif func == 'get_session_count':
|
||||
print(getSessionCount(version))
|
||||
elif func == 'clean_session_old':
|
||||
print(cleanSessionOld(version))
|
||||
elif func == 'get_disable_func':
|
||||
print(getDisableFunc(version))
|
||||
elif func == 'set_disable_func':
|
||||
|
||||
@@ -368,6 +368,151 @@ function disableFunc(version) {
|
||||
$(".soft-man-con").html(con);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function getSessionConfig(version){
|
||||
phpPost('get_session_conf', version, '', function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
if(!rdata.status){
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
return;
|
||||
}
|
||||
var rdata = rdata.data;
|
||||
|
||||
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
|
||||
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
|
||||
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
|
||||
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
|
||||
|
||||
|
||||
var info = rdata.save_path.split(":");
|
||||
var con = "<div class='conf_p'>" +
|
||||
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
|
||||
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
|
||||
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
|
||||
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
|
||||
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
|
||||
"</div>\
|
||||
<ul class='help-info-text c7'>\
|
||||
<li>若你的站点并发比较高,使用Redis,Memcache能有效提升PHP并发能力</li>\
|
||||
<li>若调整Session模式后,网站访问异常,请切换回原来的模式</li>\
|
||||
<li>切换Session模式会使在线的用户会话丢失,请在流量小的时候切换</li>\
|
||||
</ul>\
|
||||
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
|
||||
</div>\
|
||||
</div>";
|
||||
|
||||
$(".soft-man-con").html(con);
|
||||
|
||||
if (rdata.save_handler == 'file'){
|
||||
$('input[name="ip"]').attr('disabled','disabled');
|
||||
$('input[name="port"]').attr('disabled','disabled');
|
||||
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
|
||||
$('input[name="passwd"]').attr('disabled','disabled');
|
||||
}
|
||||
|
||||
// change event
|
||||
$("select[name='save_handler']").change(function() {
|
||||
var type = $(this).val();
|
||||
|
||||
var passwd = $('input[name="passwd"]').val();
|
||||
if (passwd == ""){
|
||||
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
|
||||
}
|
||||
|
||||
var ip = $('input[name="ip"]').val();
|
||||
if (ip == ""){
|
||||
$('input[name="ip"]').val('127.0.0.1');
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'redis':
|
||||
var port = $('input[name="port"]').val();
|
||||
if (port == ""){
|
||||
$('input[name="port"]').val('6379');
|
||||
}
|
||||
$('input[name="ip"]').removeAttr('disabled');
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
case 'file':
|
||||
$('input[name="ip"]').val("").attr('disabled','disabled');
|
||||
$('input[name="port"]').val("").attr('disabled','disabled');
|
||||
$('input[name="passwd"]').val("").attr('disabled','disabled');
|
||||
break;
|
||||
case 'memcache':
|
||||
var port = $('input[name="port"]').val();
|
||||
if (port == ""){
|
||||
$('input[name="port"]').val('11211');
|
||||
}
|
||||
$('input[name="ip"]').removeAttr('disabled');
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
case 'memcached':
|
||||
var port = $('input[name="port"]').val();
|
||||
if (port == ""){
|
||||
$('input[name="port"]').val('11211');
|
||||
}
|
||||
$('input[name="ip"]').removeAttr('disabled');
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
//load session stats
|
||||
phpPost('get_session_count', version, '', function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
if(!rdata.status){
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
return;
|
||||
}
|
||||
var rdata = rdata.data;
|
||||
|
||||
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
|
||||
<div class='clear_conter'>\
|
||||
<div class='session_clear_list'>\
|
||||
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
|
||||
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
|
||||
</div>\
|
||||
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
|
||||
|
||||
$("#session_clear").html(html_var);
|
||||
|
||||
|
||||
$('#clean_func').click(function(){
|
||||
phpPost('clean_session_old', version, '', function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
getSessionConfig(version);
|
||||
},{ icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function setSessionConfig(version){
|
||||
var ip = $('input[name="ip"]').val();
|
||||
var port = $('input[name="port"]').val();
|
||||
var passwd = $('input[name="passwd"]').val();
|
||||
var save_handler = $("select[name='save_handler']").val();
|
||||
var data = {
|
||||
ip:ip,
|
||||
port:port,
|
||||
passwd:passwd,
|
||||
save_handler:save_handler,
|
||||
};
|
||||
phpPost('set_session_conf', version, data, function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//设置禁用函数
|
||||
function setDisableFunc(version, act, fs) {
|
||||
var fsArr = fs.split(',');
|
||||
|
||||
@@ -5,6 +5,8 @@ group = {$PHP_GROUP}
|
||||
listen = /var/opt/remi/php{$PHP_VERSION}/run/php-fpm/www.sock
|
||||
listen.owner = {$PHP_USER}
|
||||
listen.group = {$PHP_GROUP}
|
||||
listen.backlog = 4096
|
||||
|
||||
pm = dynamic
|
||||
pm.max_children = 50
|
||||
pm.start_servers = 5
|
||||
|
||||
@@ -1,3 +1,40 @@
|
||||
<style type="text/css">
|
||||
.bt-w-main{
|
||||
height: 600px;
|
||||
}
|
||||
|
||||
.session_clear_list {
|
||||
border:1px solid #ececec;
|
||||
margin-bottom: 15px;
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.session_clear_list .line {
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #ececec;
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.session_clear_list .line:last-child {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.session_clear_list .line span{
|
||||
width: auto;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
text-align: left;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.session_clear_list .line span:first-child {
|
||||
width: 170px;
|
||||
border-right: 1px solid #ececec;
|
||||
background: #f7f7f7;
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
|
||||
<div class="bt-form">
|
||||
<div class='plugin_version'></div>
|
||||
<div class="bt-w-main">
|
||||
@@ -13,6 +50,7 @@
|
||||
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
|
||||
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
|
||||
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
|
||||
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
|
||||
<p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
|
||||
<p onclick="pluginLogs('php-yum',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
|
||||
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>
|
||||
|
||||
@@ -492,6 +492,180 @@ def getFpmStatus(version):
|
||||
return mw.returnJson(True, "OK", data)
|
||||
|
||||
|
||||
def getSessionConf(version):
|
||||
filename = getConf(version)
|
||||
if not os.path.exists(filename):
|
||||
return mw.returnJson(False, '指定PHP版本不存在!')
|
||||
|
||||
phpini = mw.readFile(filename)
|
||||
|
||||
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
|
||||
save_handler = re.search(rep, phpini)
|
||||
if save_handler:
|
||||
save_handler = save_handler.group(1)
|
||||
else:
|
||||
save_handler = "files"
|
||||
|
||||
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
|
||||
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
|
||||
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
|
||||
save_path = re.search(reppath, phpini)
|
||||
if not save_path:
|
||||
save_path = re.search(memcached, phpini)
|
||||
passwd = re.search(passrep, phpini)
|
||||
port = ""
|
||||
if passwd:
|
||||
passwd = passwd.group(1)
|
||||
else:
|
||||
passwd = ""
|
||||
if save_path:
|
||||
port = save_path.group(2)
|
||||
save_path = save_path.group(1)
|
||||
|
||||
else:
|
||||
save_path = ""
|
||||
|
||||
data = {"save_handler": save_handler, "save_path": save_path,
|
||||
"passwd": passwd, "port": port}
|
||||
return mw.returnJson(True, 'ok', data)
|
||||
|
||||
|
||||
def setSessionConf(version):
|
||||
|
||||
args = getArgs()
|
||||
|
||||
ip = args['ip']
|
||||
port = args['port']
|
||||
passwd = args['passwd']
|
||||
save_handler = args['save_handler']
|
||||
|
||||
if save_handler != "file":
|
||||
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
|
||||
if not re.search(iprep, ip):
|
||||
return mw.returnJson(False, '请输入正确的IP地址')
|
||||
|
||||
try:
|
||||
port = int(port)
|
||||
if port >= 65535 or port < 1:
|
||||
return mw.returnJson(False, '请输入正确的端口号')
|
||||
except:
|
||||
return mw.returnJson(False, '请输入正确的端口号')
|
||||
prep = r"[\~\`\/\=]"
|
||||
if re.search(prep, passwd):
|
||||
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
|
||||
|
||||
filename = getConf(version)
|
||||
if not os.path.exists(filename):
|
||||
return mw.returnJson(False, '指定PHP版本不存在!')
|
||||
phpini = mw.readFile(filename)
|
||||
|
||||
session_tmp = getServerDir() + "/tmp/session"
|
||||
|
||||
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
|
||||
val = r'session.save_handler = ' + save_handler + '\n'
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
|
||||
content = mw.execShell('cat /etc/opt/remi/php' +
|
||||
version + "/php.d/* | grep -v '^;' |tr -s '\n'")
|
||||
content = content[0]
|
||||
|
||||
if save_handler == "memcached":
|
||||
if not content.find("memcached.so") > -1:
|
||||
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
|
||||
if re.search(rep, phpini):
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "/tmp"',
|
||||
'\n;session.save_path = "/tmp"' + val, phpini)
|
||||
|
||||
if save_handler == "memcache":
|
||||
if not content.find("memcache.so") > -1:
|
||||
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
|
||||
if re.search(rep, phpini):
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "/tmp"',
|
||||
'\n;session.save_path = "/tmp"' + val, phpini)
|
||||
|
||||
if save_handler == "redis":
|
||||
if not content.find("redis.so") > -1:
|
||||
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
|
||||
if passwd:
|
||||
passwd = "?auth=" + passwd
|
||||
else:
|
||||
passwd = ""
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
|
||||
res = re.search(rep, phpini)
|
||||
if res:
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "/tmp"',
|
||||
'\n;session.save_path = "/tmp"' + val, phpini)
|
||||
|
||||
if save_handler == "file":
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "' + session_tmp + '"\n'
|
||||
if re.search(rep, phpini):
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "/tmp"',
|
||||
'\n;session.save_path = "/tmp"' + val, phpini)
|
||||
|
||||
mw.writeFile(filename, phpini)
|
||||
restart(version)
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def getSessionCount_Origin(version):
|
||||
session_tmp = getServerDir() + "/tmp/session"
|
||||
d = ["/tmp", session_tmp]
|
||||
count = 0
|
||||
for i in d:
|
||||
if not os.path.exists(i):
|
||||
mw.execShell('mkdir -p %s' % i)
|
||||
list = os.listdir(i)
|
||||
for l in list:
|
||||
if os.path.isdir(i + "/" + l):
|
||||
l1 = os.listdir(i + "/" + l)
|
||||
for ll in l1:
|
||||
if "sess_" in ll:
|
||||
count += 1
|
||||
continue
|
||||
if "sess_" in l:
|
||||
count += 1
|
||||
|
||||
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
|
||||
old_file = int(mw.execShell(s)[0].split("\n")[0])
|
||||
|
||||
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
|
||||
old_file += int(mw.execShell(s)[0].split("\n")[0])
|
||||
return {"total": count, "oldfile": old_file}
|
||||
|
||||
|
||||
def getSessionCount(version):
|
||||
data = getSessionCount_Origin(version)
|
||||
return mw.returnJson(True, 'ok!', data)
|
||||
|
||||
|
||||
def cleanSessionOld(version):
|
||||
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
|
||||
mw.execShell(s)
|
||||
|
||||
session_tmp = getServerDir() + "/tmp/session"
|
||||
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
|
||||
mw.execShell(s)
|
||||
old_file_conf = getSessionCount_Origin(version)["oldfile"]
|
||||
if old_file_conf == 0:
|
||||
return mw.returnJson(True, '清理成功')
|
||||
else:
|
||||
return mw.returnJson(True, '清理失败')
|
||||
|
||||
|
||||
def getDisableFunc(version):
|
||||
filename = getConf(version)
|
||||
if not os.path.exists(filename):
|
||||
@@ -689,6 +863,14 @@ if __name__ == "__main__":
|
||||
print(setFpmConfig(version))
|
||||
elif func == 'get_fpm_status':
|
||||
print(getFpmStatus(version))
|
||||
elif func == 'get_session_conf':
|
||||
print(getSessionConf(version))
|
||||
elif func == 'set_session_conf':
|
||||
print(setSessionConf(version))
|
||||
elif func == 'get_session_count':
|
||||
print(getSessionCount(version))
|
||||
elif func == 'clean_session_old':
|
||||
print(cleanSessionOld(version))
|
||||
elif func == 'get_disable_func':
|
||||
print(getDisableFunc(version))
|
||||
elif func == 'set_disable_func':
|
||||
|
||||
@@ -340,6 +340,147 @@ function getFpmStatus(version){
|
||||
});
|
||||
}
|
||||
|
||||
function getSessionConfig(version){
|
||||
phpPost('get_session_conf', version, '', function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
if(!rdata.status){
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
return;
|
||||
}
|
||||
var rdata = rdata.data;
|
||||
|
||||
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
|
||||
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
|
||||
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
|
||||
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
|
||||
|
||||
|
||||
var info = rdata.save_path.split(":");
|
||||
var con = "<div class='conf_p'>" +
|
||||
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
|
||||
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
|
||||
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
|
||||
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
|
||||
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
|
||||
"</div>\
|
||||
<ul class='help-info-text c7'>\
|
||||
<li>若你的站点并发比较高,使用Redis,Memcache能有效提升PHP并发能力</li>\
|
||||
<li>若调整Session模式后,网站访问异常,请切换回原来的模式</li>\
|
||||
<li>切换Session模式会使在线的用户会话丢失,请在流量小的时候切换</li>\
|
||||
</ul>\
|
||||
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
|
||||
</div>\
|
||||
</div>";
|
||||
|
||||
$(".soft-man-con").html(con);
|
||||
|
||||
if (rdata.save_handler == 'file'){
|
||||
$('input[name="ip"]').attr('disabled','disabled');
|
||||
$('input[name="port"]').attr('disabled','disabled');
|
||||
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
|
||||
$('input[name="passwd"]').attr('disabled','disabled');
|
||||
}
|
||||
|
||||
// change event
|
||||
$("select[name='save_handler']").change(function() {
|
||||
var type = $(this).val();
|
||||
|
||||
var passwd = $('input[name="passwd"]').val();
|
||||
if (passwd == ""){
|
||||
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
|
||||
}
|
||||
|
||||
var ip = $('input[name="ip"]').val();
|
||||
if (ip == ""){
|
||||
$('input[name="ip"]').val('127.0.0.1');
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'redis':
|
||||
var port = $('input[name="port"]').val();
|
||||
if (port == ""){
|
||||
$('input[name="port"]').val('6379');
|
||||
}
|
||||
$('input[name="ip"]').removeAttr('disabled');
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
case 'file':
|
||||
$('input[name="ip"]').val("").attr('disabled','disabled');
|
||||
$('input[name="port"]').val("").attr('disabled','disabled');
|
||||
$('input[name="passwd"]').val("").attr('disabled','disabled');
|
||||
break;
|
||||
case 'memcache':
|
||||
var port = $('input[name="port"]').val();
|
||||
if (port == ""){
|
||||
$('input[name="port"]').val('11211');
|
||||
}
|
||||
$('input[name="ip"]').removeAttr('disabled');
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
case 'memcached':
|
||||
var port = $('input[name="port"]').val();
|
||||
if (port == ""){
|
||||
$('input[name="port"]').val('11211');
|
||||
}
|
||||
$('input[name="ip"]').removeAttr('disabled');
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
//load session stats
|
||||
phpPost('get_session_count', version, '', function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
if(!rdata.status){
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
return;
|
||||
}
|
||||
var rdata = rdata.data;
|
||||
|
||||
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
|
||||
<div class='clear_conter'>\
|
||||
<div class='session_clear_list'>\
|
||||
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
|
||||
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
|
||||
</div>\
|
||||
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
|
||||
|
||||
$("#session_clear").html(html_var);
|
||||
|
||||
|
||||
$('#clean_func').click(function(){
|
||||
phpPost('clean_session_old', version, '', function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
getSessionConfig(version);
|
||||
},{ icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function setSessionConfig(version){
|
||||
var ip = $('input[name="ip"]').val();
|
||||
var port = $('input[name="port"]').val();
|
||||
var passwd = $('input[name="passwd"]').val();
|
||||
var save_handler = $("select[name='save_handler']").val();
|
||||
var data = {
|
||||
ip:ip,
|
||||
port:port,
|
||||
passwd:passwd,
|
||||
save_handler:save_handler,
|
||||
};
|
||||
phpPost('set_session_conf', version, data, function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
}
|
||||
|
||||
//禁用函数
|
||||
function disableFunc(version) {
|
||||
phpPost('get_disable_func', version,'',function(data){
|
||||
|
||||
@@ -1,9 +1,12 @@
|
||||
[www]
|
||||
user = {$PHP_USER}
|
||||
group = {$PHP_GROUP}
|
||||
|
||||
listen = /tmp/php-cgi-{$PHP_VERSION}.sock
|
||||
listen.owner = {$PHP_USER}
|
||||
listen.group = {$PHP_GROUP}
|
||||
listen.backlog = 4096
|
||||
|
||||
pm = dynamic
|
||||
pm.max_children = 50
|
||||
pm.start_servers = 5
|
||||
|
||||
+40
-1
@@ -1,6 +1,43 @@
|
||||
|
||||
<style type="text/css">
|
||||
.bt-w-main{
|
||||
height: 642px;
|
||||
}
|
||||
|
||||
.session_clear_list {
|
||||
border:1px solid #ececec;
|
||||
margin-bottom: 15px;
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.session_clear_list .line {
|
||||
padding: 0;
|
||||
border-bottom: 1px solid #ececec;
|
||||
width: 270px;
|
||||
}
|
||||
|
||||
.session_clear_list .line:last-child {
|
||||
border-bottom: 0px;
|
||||
}
|
||||
|
||||
.session_clear_list .line span{
|
||||
width: auto;
|
||||
height: 35px;
|
||||
line-height: 35px;
|
||||
text-align: left;
|
||||
padding: 0 5px;
|
||||
}
|
||||
|
||||
.session_clear_list .line span:first-child {
|
||||
width: 170px;
|
||||
border-right: 1px solid #ececec;
|
||||
background: #f7f7f7;
|
||||
float: left;
|
||||
}
|
||||
</style>
|
||||
<div class="bt-form">
|
||||
<div class='plugin_version'></div>
|
||||
<div class="bt-w-main">
|
||||
<div class="bt-w-main" >
|
||||
<div class="bt-w-menu">
|
||||
<p class="bgw" onclick="pluginService('php', $('.plugin_version').attr('version'));">服务</p>
|
||||
<p onclick="pluginInitD('php', $('.plugin_version').attr('version'));">自启动</p>
|
||||
@@ -13,6 +50,7 @@
|
||||
<p onclick="disableFunc($('.plugin_version').attr('version'));">禁用函数</p>
|
||||
<p onclick="getFpmConfig($('.plugin_version').attr('version'));">性能调整</p>
|
||||
<p onclick="getFpmStatus($('.plugin_version').attr('version'));">负载状况</p>
|
||||
<p onclick="getSessionConfig($('.plugin_version').attr('version'));" title="session管理">会话管理</p>
|
||||
<p onclick="pluginLogs('php',$('.plugin_version').attr('version'),'fpm_log');">FPM日志</p>
|
||||
<p onclick="pluginLogs('php',$('.plugin_version').attr('version'),'fpm_slow_log');">慢日志</p>
|
||||
<p onclick="getPhpinfo($('.plugin_version').attr('version'));">PHPIFNO</p>
|
||||
@@ -24,6 +62,7 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript">
|
||||
$.getScript( "/plugins/file?name=php&f=js/php.js", function(){
|
||||
pluginService('php', $('.plugin_version').attr('version'));
|
||||
|
||||
@@ -632,6 +632,176 @@ def getFpmStatus(version):
|
||||
return mw.returnJson(True, "OK", data)
|
||||
|
||||
|
||||
def getSessionConf(version):
|
||||
filename = getConf(version)
|
||||
if not os.path.exists(filename):
|
||||
return mw.returnJson(False, '指定PHP版本不存在!')
|
||||
|
||||
phpini = mw.readFile(filename)
|
||||
|
||||
rep = r'session.save_handler\s*=\s*([0-9A-Za-z_& ~]+)(\s*;?|\r?\n)'
|
||||
save_handler = re.search(rep, phpini)
|
||||
if save_handler:
|
||||
save_handler = save_handler.group(1)
|
||||
else:
|
||||
save_handler = "files"
|
||||
|
||||
reppath = r'\nsession.save_path\s*=\s*"tcp\:\/\/([\d\.]+):(\d+).*\r?\n'
|
||||
passrep = r'\nsession.save_path\s*=\s*"tcp://[\w\.\?\:]+=(.*)"\r?\n'
|
||||
memcached = r'\nsession.save_path\s*=\s*"([\d\.]+):(\d+)"'
|
||||
save_path = re.search(reppath, phpini)
|
||||
if not save_path:
|
||||
save_path = re.search(memcached, phpini)
|
||||
passwd = re.search(passrep, phpini)
|
||||
port = ""
|
||||
if passwd:
|
||||
passwd = passwd.group(1)
|
||||
else:
|
||||
passwd = ""
|
||||
if save_path:
|
||||
port = save_path.group(2)
|
||||
save_path = save_path.group(1)
|
||||
|
||||
else:
|
||||
save_path = ""
|
||||
|
||||
data = {"save_handler": save_handler, "save_path": save_path,
|
||||
"passwd": passwd, "port": port}
|
||||
return mw.returnJson(True, 'ok', data)
|
||||
|
||||
|
||||
def setSessionConf(version):
|
||||
|
||||
args = getArgs()
|
||||
|
||||
ip = args['ip']
|
||||
port = args['port']
|
||||
passwd = args['passwd']
|
||||
save_handler = args['save_handler']
|
||||
|
||||
if save_handler != "file":
|
||||
iprep = r"(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})\.(2(5[0-5]{1}|[0-4]\d{1})|[0-1]?\d{1,2})"
|
||||
if not re.search(iprep, ip):
|
||||
return mw.returnJson(False, '请输入正确的IP地址')
|
||||
|
||||
try:
|
||||
port = int(port)
|
||||
if port >= 65535 or port < 1:
|
||||
return mw.returnJson(False, '请输入正确的端口号')
|
||||
except:
|
||||
return mw.returnJson(False, '请输入正确的端口号')
|
||||
prep = r"[\~\`\/\=]"
|
||||
if re.search(prep, passwd):
|
||||
return mw.returnJson(False, '请不要输入以下特殊字符 " ~ ` / = "')
|
||||
|
||||
filename = getConf(version)
|
||||
if not os.path.exists(filename):
|
||||
return mw.returnJson(False, '指定PHP版本不存在!')
|
||||
phpini = mw.readFile(filename)
|
||||
|
||||
session_tmp = getServerDir() + "/tmp/session"
|
||||
|
||||
rep = r'session.save_handler\s*=\s*(.+)\r?\n'
|
||||
val = r'session.save_handler = ' + save_handler + '\n'
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
|
||||
if save_handler == "memcached":
|
||||
if not re.search("memcached.so", phpini):
|
||||
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
|
||||
if re.search(rep, phpini):
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
|
||||
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
|
||||
|
||||
if save_handler == "memcache":
|
||||
if not re.search("memcache.so", phpini):
|
||||
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "%s:%s" \n' % (ip, port)
|
||||
if re.search(rep, phpini):
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
|
||||
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
|
||||
|
||||
if save_handler == "redis":
|
||||
if not re.search("redis.so", phpini):
|
||||
return mw.returnJson(False, '请先安装%s扩展' % save_handler)
|
||||
if passwd:
|
||||
passwd = "?auth=" + passwd
|
||||
else:
|
||||
passwd = ""
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "tcp://%s:%s%s"\n' % (ip, port, passwd)
|
||||
res = re.search(rep, phpini)
|
||||
if res:
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
|
||||
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
|
||||
|
||||
if save_handler == "file":
|
||||
rep = r'\nsession.save_path\s*=\s*(.+)\r?\n'
|
||||
val = r'\nsession.save_path = "' + session_tmp + '"\n'
|
||||
if re.search(rep, phpini):
|
||||
phpini = re.sub(rep, val, phpini)
|
||||
else:
|
||||
phpini = re.sub('\n;session.save_path = "' + session_tmp + '"',
|
||||
'\n;session.save_path = "' + session_tmp + '"' + val, phpini)
|
||||
|
||||
mw.writeFile(filename, phpini)
|
||||
reload(version)
|
||||
return mw.returnJson(True, '设置成功!')
|
||||
|
||||
|
||||
def getSessionCount_Origin(version):
|
||||
session_tmp = getServerDir() + "/tmp/session"
|
||||
d = [session_tmp]
|
||||
count = 0
|
||||
for i in d:
|
||||
if not os.path.exists(i):
|
||||
mw.execShell('mkdir -p %s' % i)
|
||||
list = os.listdir(i)
|
||||
for l in list:
|
||||
if os.path.isdir(i + "/" + l):
|
||||
l1 = os.listdir(i + "/" + l)
|
||||
for ll in l1:
|
||||
if "sess_" in ll:
|
||||
count += 1
|
||||
continue
|
||||
if "sess_" in l:
|
||||
count += 1
|
||||
|
||||
s = "find /tmp -mtime +1 |grep 'sess_' | wc -l"
|
||||
old_file = int(mw.execShell(s)[0].split("\n")[0])
|
||||
|
||||
s = "find " + session_tmp + " -mtime +1 |grep 'sess_'|wc -l"
|
||||
old_file += int(mw.execShell(s)[0].split("\n")[0])
|
||||
return {"total": count, "oldfile": old_file}
|
||||
|
||||
|
||||
def getSessionCount(version):
|
||||
data = getSessionCount_Origin(version)
|
||||
return mw.returnJson(True, 'ok!', data)
|
||||
|
||||
|
||||
def cleanSessionOld(version):
|
||||
s = "find /tmp -mtime +1 |grep 'sess_'|xargs rm -f"
|
||||
mw.execShell(s)
|
||||
|
||||
session_tmp = getServerDir() + "/tmp/session"
|
||||
s = "find " + session_tmp + " -mtime +1 |grep 'sess_' |xargs rm -f"
|
||||
mw.execShell(s)
|
||||
old_file_conf = getSessionCount_Origin(version)["oldfile"]
|
||||
if old_file_conf == 0:
|
||||
return mw.returnJson(True, '清理成功')
|
||||
else:
|
||||
return mw.returnJson(True, '清理失败')
|
||||
|
||||
|
||||
def getDisableFunc(version):
|
||||
filename = getConf(version)
|
||||
if not os.path.exists(filename):
|
||||
@@ -794,6 +964,7 @@ def installPreInspection(version):
|
||||
return 'fedora[{}]不可安装'.format(sysId)
|
||||
return 'ok'
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
if len(sys.argv) < 3:
|
||||
@@ -847,6 +1018,14 @@ if __name__ == "__main__":
|
||||
print(setFpmConfig(version))
|
||||
elif func == 'get_fpm_status':
|
||||
print(getFpmStatus(version))
|
||||
elif func == 'get_session_conf':
|
||||
print(getSessionConf(version))
|
||||
elif func == 'set_session_conf':
|
||||
print(setSessionConf(version))
|
||||
elif func == 'get_session_count':
|
||||
print(getSessionCount(version))
|
||||
elif func == 'clean_session_old':
|
||||
print(cleanSessionOld(version))
|
||||
elif func == 'get_disable_func':
|
||||
print(getDisableFunc(version))
|
||||
elif func == 'set_disable_func':
|
||||
|
||||
+146
-14
@@ -1,14 +1,3 @@
|
||||
|
||||
function str2Obj(str){
|
||||
var data = {};
|
||||
kv = str.split('&');
|
||||
for(i in kv){
|
||||
v = kv[i].split('=');
|
||||
data[v[0]] = v[1];
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
function phpPost(method, version, args,callback){
|
||||
var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 });
|
||||
|
||||
@@ -18,7 +7,7 @@ function phpPost(method, version, args,callback){
|
||||
req_data['version'] = version;
|
||||
|
||||
if (typeof(args) == 'string'){
|
||||
req_data['args'] = JSON.stringify(str2Obj(args));
|
||||
req_data['args'] = JSON.stringify(toArrayObject(args));
|
||||
} else {
|
||||
req_data['args'] = JSON.stringify(args);
|
||||
}
|
||||
@@ -46,7 +35,7 @@ function phpPostCallbak(method, version, args,callback){
|
||||
args['version'] = version;
|
||||
|
||||
if (typeof(args) == 'string'){
|
||||
req_data['args'] = JSON.stringify(str2Obj(args));
|
||||
req_data['args'] = JSON.stringify(toArrayObject(args));
|
||||
} else {
|
||||
req_data['args'] = JSON.stringify(args);
|
||||
}
|
||||
@@ -194,7 +183,7 @@ function getFpmConfig(version){
|
||||
"<option value='3' " + (rdata.max_children == 100 ? 'selected' : '') + ">100并发</option>" +
|
||||
"<option value='4' " + (rdata.max_children == 200 ? 'selected' : '') + ">200并发</option>" +
|
||||
"<option value='5' " + (rdata.max_children == 300 ? 'selected' : '') + ">300并发</option>" +
|
||||
"<option value='6' " + (rdata.max_children == 500 ? 'selected' : '') + ">500并发</option>"
|
||||
"<option value='6' " + (rdata.max_children == 500 ? 'selected' : '') + ">500并发</option>";
|
||||
var pms = [{ 'name': 'static', 'title': '静态' }, { 'name': 'dynamic', 'title': '动态' }];
|
||||
var pmList = '';
|
||||
for (var i = 0; i < pms.length; i++) {
|
||||
@@ -340,6 +329,149 @@ function getFpmStatus(version){
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function getSessionConfig(version){
|
||||
phpPost('get_session_conf', version, '', function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
if(!rdata.status){
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
return;
|
||||
}
|
||||
var rdata = rdata.data;
|
||||
|
||||
var cacheList = "<option value='file' " + (rdata.save_handler == "file" ? 'selected' : '') + ">file</option>" +
|
||||
"<option value='redis' " + (rdata.save_handler == "redis" ? 'selected' : '') + ">redis</option>" +
|
||||
"<option value='memcache' " + (rdata.save_handler == "memcache" ? 'selected' : '') + ">memcache</option>" +
|
||||
"<option value='memcached' " + (rdata.save_handler == "memcached" ? 'selected' : '') + ">memcached</option>";
|
||||
|
||||
|
||||
var info = rdata.save_path.split(":");
|
||||
var con = "<div class='conf_p'>" +
|
||||
"<p class='line'><span class='span_tit'>存储模式:</span><select class='bt-input-text' name='save_handler' style='width:200px;'>" + cacheList + "</select></p>" +
|
||||
"<p class='line'><span class='span_tit'>IP地址:</span><input class='bt-input-text' type='text' name='ip' style='width:200px;' value='"+ info[0] +"' /></p>" +
|
||||
"<p class='line'><span class='span_tit'>端口:</span><input class='bt-input-text' type='text' name='port' style='width:200px;' value='"+rdata.port+"' /></p>" +
|
||||
"<p class='line'><span class='span_tit'>密码:</span><input class='bt-input-text' type='text' name='passwd' style='width:200px;' value='"+rdata.passwd+"' /></p>" +
|
||||
"<p class='line'><div class='mtb15' style='margin-left:100px;'><button class='btn btn-success btn-sm' onclick='setSessionConfig(\"" + version + "\",1)'>保存</button></div></p>" +
|
||||
"</div>\
|
||||
<ul class='help-info-text c7'>\
|
||||
<li>若你的站点并发比较高,使用Redis,Memcache能有效提升PHP并发能力</li>\
|
||||
<li>若调整Session模式后,网站访问异常,请切换回原来的模式</li>\
|
||||
<li>切换Session模式会使在线的用户会话丢失,请在流量小的时候切换</li>\
|
||||
</ul>\
|
||||
<div id='session_clear' class='session_clear' style='border-top: #ccc 1px dashed;padding-top: 15px;margin-top: 15px;'>\
|
||||
</div>\
|
||||
</div>";
|
||||
|
||||
$(".soft-man-con").html(con);
|
||||
|
||||
if (rdata.save_handler == 'file'){
|
||||
$('input[name="ip"]').attr('disabled','disabled');
|
||||
$('input[name="port"]').attr('disabled','disabled');
|
||||
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
|
||||
$('input[name="passwd"]').attr('disabled','disabled');
|
||||
}
|
||||
|
||||
// change event
|
||||
$("select[name='save_handler']").change(function() {
|
||||
var type = $(this).val();
|
||||
|
||||
var passwd = $('input[name="passwd"]').val();
|
||||
if (passwd == ""){
|
||||
$('input[name="passwd"]').attr('placeholder','如果没有密码留空');
|
||||
}
|
||||
|
||||
var ip = $('input[name="ip"]').val();
|
||||
if (ip == ""){
|
||||
$('input[name="ip"]').val('127.0.0.1');
|
||||
}
|
||||
|
||||
switch (type) {
|
||||
case 'redis':
|
||||
var port = $('input[name="port"]').val();
|
||||
if (port == ""){
|
||||
$('input[name="port"]').val('6379');
|
||||
}
|
||||
$('input[name="ip"]').removeAttr('disabled');
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
case 'file':
|
||||
$('input[name="ip"]').val("").attr('disabled','disabled');
|
||||
$('input[name="port"]').val("").attr('disabled','disabled');
|
||||
$('input[name="passwd"]').val("").attr('disabled','disabled');
|
||||
break;
|
||||
case 'memcache':
|
||||
var port = $('input[name="port"]').val();
|
||||
if (port == ""){
|
||||
$('input[name="port"]').val('11211');
|
||||
}
|
||||
$('input[name="ip"]').removeAttr('disabled');
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
case 'memcached':
|
||||
var port = $('input[name="port"]').val();
|
||||
if (port == ""){
|
||||
$('input[name="port"]').val('11211');
|
||||
}
|
||||
$('input[name="ip"]').removeAttr('disabled');
|
||||
$('input[name="port"]').removeAttr('disabled');
|
||||
$('input[name="passwd"]').removeAttr('disabled');
|
||||
break;
|
||||
}
|
||||
});
|
||||
|
||||
//load session stats
|
||||
phpPost('get_session_count', version, '', function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
if(!rdata.status){
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
return;
|
||||
}
|
||||
var rdata = rdata.data;
|
||||
|
||||
var html_var = "<div class='clear_title' style='padding-bottom:15px;'>清理Session文件</div>\
|
||||
<div class='clear_conter'>\
|
||||
<div class='session_clear_list'>\
|
||||
<div class='line'><span>总Session文件数量</span><span>"+rdata.total+"</span></div>\
|
||||
<div class='line'><span>可清理的Session文件数量</span><span>"+rdata.oldfile+"</span></div>\
|
||||
</div>\
|
||||
<button id='clean_func' class='btn btn-success btn-sm clear_session_file'>清理session文件</button>";
|
||||
|
||||
$("#session_clear").html(html_var);
|
||||
|
||||
|
||||
$('#clean_func').click(function(){
|
||||
phpPost('clean_session_old', version, '', function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
showMsg(rdata.msg,function(){
|
||||
getSessionConfig(version);
|
||||
},{ icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function setSessionConfig(version){
|
||||
var ip = $('input[name="ip"]').val();
|
||||
var port = $('input[name="port"]').val();
|
||||
var passwd = $('input[name="passwd"]').val();
|
||||
var save_handler = $("select[name='save_handler']").val();
|
||||
var data = {
|
||||
ip:ip,
|
||||
port:port,
|
||||
passwd:passwd,
|
||||
save_handler:save_handler,
|
||||
};
|
||||
phpPost('set_session_conf', version, data, function(ret_data){
|
||||
var rdata = $.parseJSON(ret_data.data);
|
||||
layer.msg(rdata.msg, { icon: rdata.status ? 1 : 2 });
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
//禁用函数
|
||||
function disableFunc(version) {
|
||||
phpPost('get_disable_func', version,'',function(data){
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
daemonize yes
|
||||
pidfile {$SERVER_PATH}/redis/redis_6379.pid
|
||||
|
||||
bind 127.0.0.1
|
||||
bind 0.0.0.0
|
||||
port 6379
|
||||
requirepass admin
|
||||
|
||||
|
||||
+13
-3
@@ -125,7 +125,7 @@ def redisOp(method):
|
||||
data = mw.execShell('systemctl ' + method + ' redis')
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
return data[1]
|
||||
|
||||
data = mw.execShell(file + ' start')
|
||||
if data[1] == '':
|
||||
@@ -154,6 +154,10 @@ def reload():
|
||||
|
||||
|
||||
def runInfo():
|
||||
s = status()
|
||||
if s == 'stop':
|
||||
return mw.returnJson(False, '未启动')
|
||||
|
||||
requirepass = ""
|
||||
|
||||
conf = getServerDir() + '/redis.conf'
|
||||
@@ -163,9 +167,15 @@ def runInfo():
|
||||
if tmp:
|
||||
requirepass = tmp.groups()[1]
|
||||
|
||||
cmd = getServerDir() + "/bin/redis-cli info"
|
||||
default_ip = '0.0.0.0'
|
||||
findDebian = mw.execShell('cat /etc/issue |grep Debian')
|
||||
if findDebian[0] != '':
|
||||
default_ip = mw.getLocalIp()
|
||||
|
||||
cmd = getServerDir() + "/bin/redis-cli -h " + default_ip + " info"
|
||||
if requirepass != "":
|
||||
cmd = getServerDir() + '/bin/redis-cli -a "' + requirepass + '" info'
|
||||
cmd = getServerDir() + '/bin/redis-cli -h ' + default_ip + \
|
||||
' -a "' + requirepass + '" info'
|
||||
|
||||
data = mw.execShell(cmd)[0]
|
||||
res = [
|
||||
|
||||
@@ -5,7 +5,6 @@ After=network.target
|
||||
[Service]
|
||||
Type=forking
|
||||
ExecStart={$SERVER_PATH}/redis/bin/redis-server {$SERVER_PATH}/redis/redis.conf
|
||||
ExecStop={$SERVER_PATH}/redis/redis-cli shutdown
|
||||
ExecReload=/bin/kill -USR2 $MAINPID
|
||||
Restart=on-failure
|
||||
|
||||
|
||||
@@ -69,6 +69,11 @@ function redisStatus(version) {
|
||||
|
||||
redisPost('run_info',version, {},function(data){
|
||||
var rdata = $.parseJSON(data.data);
|
||||
// if (!rdata.status){
|
||||
// layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']});
|
||||
// return;
|
||||
// }
|
||||
|
||||
hit = (parseInt(rdata.keyspace_hits) / (parseInt(rdata.keyspace_hits) + parseInt(rdata.keyspace_misses)) * 100).toFixed(2);
|
||||
var con = '<div class="divtable">\
|
||||
<table class="table table-hover table-bordered" style="width: 490px;">\
|
||||
|
||||
@@ -117,7 +117,7 @@ def swapOp(method):
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
|
||||
data = mw.execShell(file + ' start')
|
||||
data = mw.execShell(file + ' ' + method)
|
||||
if data[1] == '':
|
||||
return 'ok'
|
||||
return 'fail'
|
||||
@@ -136,7 +136,7 @@ def restart():
|
||||
|
||||
|
||||
def reload():
|
||||
return swapOp('reload')
|
||||
return 'ok'
|
||||
|
||||
|
||||
def initdStatus():
|
||||
@@ -185,14 +185,15 @@ def changeSwap():
|
||||
|
||||
size = args['size']
|
||||
swapOp('stop')
|
||||
os.system('dd if=/dev/zero of=' + getServerDir() +
|
||||
'/swapfile bs=1M count=' + size)
|
||||
|
||||
os.system('mkswap ' + getServerDir() + '/swapfile')
|
||||
os.system('chmod 600 ' + getServerDir() + '/swapfile')
|
||||
gsdir = getServerDir()
|
||||
|
||||
cmd = 'dd if=/dev/zero of=' + gsdir + '/swapfile bs=1M count=' + size
|
||||
cmd += ' && mkswap ' + gsdir + '/swapfile && chmod 600 ' + gsdir + '/swapfile'
|
||||
msg = mw.execShell(cmd)
|
||||
swapOp('start')
|
||||
|
||||
return mw.returnJson(True, "修改成功!")
|
||||
return mw.returnJson(True, "修改成功:\n" + msg[0])
|
||||
|
||||
if __name__ == "__main__":
|
||||
func = sys.argv[1]
|
||||
|
||||
@@ -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.tcp_keepalive_time = 30
|
||||
net.ipv4.tcp_max_tw_buckets = 8000
|
||||
net.ipv4.tcp_tw_reuse = 1
|
||||
net.ipv4.tcp_tw_recycle = 1
|
||||
net.ipv4.ip_forward = 0
|
||||
net.ipv4.conf.default.rp_filter = 1
|
||||
net.ipv4.conf.default.accept_source_route = 0
|
||||
kernel.sysrq = 0
|
||||
kernel.core_uses_pid = 1
|
||||
net.ipv4.tcp_syncookies = 1
|
||||
net.ipv4.tcp_max_syn_backlog = 30000
|
||||
net.ipv4.tcp_syn_retries = 2
|
||||
net.ipv4.tcp_synack_retries = 2
|
||||
net.ipv4.ip_local_port_range = 1025 61000
|
||||
net.ipv4.tcp_keepalive_intvl = 3
|
||||
net.ipv4.tcp_keepalive_probes = 2
|
||||
kernel.msgmnb = 65536
|
||||
kernel.msgmax = 65536
|
||||
kernel.shmmax = 68719476736
|
||||
kernel.shmall = 4294967296
|
||||
net.ipv4.tcp_max_tw_buckets = 6000
|
||||
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
|
||||
@@ -1,2 +1,2 @@
|
||||
lua_shared_dict mw_total 50m;
|
||||
lua_shared_dict mw_total 100m;
|
||||
include {$SERVER_APP}/lua/webstats_log.lua;
|
||||
+35
-15
@@ -77,11 +77,11 @@ def status():
|
||||
return 'start'
|
||||
|
||||
|
||||
def loadLuaLogFile():
|
||||
def loadLuaFile(name):
|
||||
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 = content.replace('{$SERVER_APP}', getServerDir())
|
||||
content = content.replace('{$ROOT_PATH}', mw.getServerDir())
|
||||
@@ -98,7 +98,7 @@ def loadConfigFile():
|
||||
dst_conf_json = getServerDir() + "/lua/config.json"
|
||||
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)
|
||||
|
||||
|
||||
@@ -125,9 +125,16 @@ def loadLuaSiteFile():
|
||||
ddata["default"] = "unset"
|
||||
else:
|
||||
ddata["default"] = dlist[0]
|
||||
|
||||
mw.writeFile(default_json, json.dumps(ddata))
|
||||
|
||||
lua_site = lua_dir + "/sites.lua"
|
||||
lua_site = lua_dir + "/webstats_sites.lua"
|
||||
|
||||
tmp = {
|
||||
"name": "unset",
|
||||
"domain": [],
|
||||
}
|
||||
content.append(tmp)
|
||||
listToLuaFile(lua_site, content)
|
||||
|
||||
|
||||
@@ -205,7 +212,14 @@ def initDreplace():
|
||||
if not os.path.exists(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()
|
||||
loadLuaSiteFile()
|
||||
loadDebugLogFile()
|
||||
@@ -222,28 +236,35 @@ def start():
|
||||
if not mw.isAppleSystem():
|
||||
mw.execShell("chown -R www:www " + getServerDir())
|
||||
|
||||
mw.restartWeb()
|
||||
mw.opWeb("reload")
|
||||
return 'ok'
|
||||
|
||||
|
||||
def stop():
|
||||
path = luaConf()
|
||||
os.remove(path)
|
||||
mw.restartWeb()
|
||||
if os.path.exists(path):
|
||||
os.remove(path)
|
||||
|
||||
import tool_task
|
||||
tool_task.removeBgTask()
|
||||
|
||||
mw.opWeb("restart")
|
||||
return 'ok'
|
||||
|
||||
|
||||
def restart():
|
||||
initDreplace()
|
||||
|
||||
mw.opWeb("reload")
|
||||
return 'ok'
|
||||
|
||||
|
||||
def reload():
|
||||
initDreplace()
|
||||
|
||||
loadLuaLogFile()
|
||||
loadDebugLogFile()
|
||||
mw.restartWeb()
|
||||
|
||||
mw.opWeb("reload")
|
||||
return 'ok'
|
||||
|
||||
|
||||
@@ -294,7 +315,7 @@ def setGlobalConf():
|
||||
content['global']['exclude_url'] = exclude_url_val
|
||||
|
||||
mw.writeFile(conf, json.dumps(content))
|
||||
conf_lua = getServerDir() + "/lua/config.lua"
|
||||
conf_lua = getServerDir() + "/lua/webstats_config.lua"
|
||||
listToLuaFile(conf_lua, content)
|
||||
mw.restartWeb()
|
||||
return mw.returnJson(True, '设置成功')
|
||||
@@ -387,7 +408,7 @@ def setSiteConf():
|
||||
content[domain] = site_conf
|
||||
|
||||
mw.writeFile(conf, json.dumps(content))
|
||||
conf_lua = getServerDir() + "/lua/config.lua"
|
||||
conf_lua = getServerDir() + "/lua/webstats_config.lua"
|
||||
listToLuaFile(conf_lua, content)
|
||||
mw.restartWeb()
|
||||
return mw.returnJson(True, '设置成功')
|
||||
@@ -622,7 +643,7 @@ def getLogsList():
|
||||
limit = str(page_size) + ' offset ' + str(page_size * (page - 1))
|
||||
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 = ''
|
||||
conn = conn.field(field)
|
||||
conn = conn.where("1=1", ())
|
||||
@@ -1101,7 +1122,6 @@ def getUriStatList():
|
||||
conn = conn.where("day>? and flow>?", (0, 0,))
|
||||
|
||||
clist = conn.order("flow desc").limit("50").inquiry(origin_field)
|
||||
# print(clist)
|
||||
|
||||
total_req = 0
|
||||
total_flow = 0
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
"name": "webstats",
|
||||
"title": "网站统计",
|
||||
"shell": "install.sh",
|
||||
"versions":["0.2.0"],
|
||||
"versions":["0.2.2"],
|
||||
"tip": "soft",
|
||||
"install_pre_inspection":true,
|
||||
"checks": "server/webstats",
|
||||
|
||||
+18
-14
@@ -24,12 +24,14 @@ if [ -f ${rootPath}/bin/activate ];then
|
||||
source ${rootPath}/bin/activate
|
||||
fi
|
||||
|
||||
get_latest_release() {
|
||||
curl -sL "https://api.github.com/repos/$1/releases/latest" | grep '"tag_name":' | cut -d'"' -f4
|
||||
}
|
||||
|
||||
Install_App()
|
||||
{
|
||||
echo '正在安装脚本文件...' > $install_tmp
|
||||
mkdir -p $serverPath/source/webstats
|
||||
|
||||
|
||||
mkdir -p $serverPath/webstats
|
||||
|
||||
# 下载源码安装包
|
||||
@@ -88,29 +90,31 @@ Install_App()
|
||||
|
||||
# https://github.com/P3TERX/GeoLite.mmdb
|
||||
pip install geoip2
|
||||
if [ ! -f $serverPath/webstats/GeoLite2-City.mmdb ];then
|
||||
# pip install geoip2
|
||||
wget --no-check-certificate -O $serverPath/webstats/GeoLite2-City.mmdb https://git.io/GeoLite2-City.mmdb
|
||||
# if [ ! -f $serverPath/webstats/GeoLite2-City.mmdb ];then
|
||||
# wget --no-check-certificate -O $serverPath/webstats/GeoLite2-City.mmdb https://github.com/P3TERX/GeoLite.mmdb/releases/download/2022.10.16/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
|
||||
|
||||
# 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 '安装完成' > $install_tmp
|
||||
|
||||
if [ "$sys_os" != "Darwin" ];then
|
||||
cd $rootPath && python3 ${rootPath}/plugins/webstats/index.py start
|
||||
fi
|
||||
cd $rootPath && python3 ${rootPath}/plugins/webstats/index.py start
|
||||
}
|
||||
|
||||
Uninstall_App()
|
||||
{
|
||||
if [ "$sys_os" != "Darwin" ];then
|
||||
cd $rootPath && python3 ${rootPath}/plugins/webstats/index.py stop
|
||||
fi
|
||||
|
||||
cd $rootPath && python3 ${rootPath}/plugins/webstats/index.py stop
|
||||
rm -rf $serverPath/webstats
|
||||
echo "Uninstall_redis" > $install_tmp
|
||||
echo "卸载完成" > $install_tmp
|
||||
}
|
||||
|
||||
action=$1
|
||||
|
||||
@@ -247,7 +247,7 @@ wsPost('get_global_conf', '' ,{}, function(rdata){
|
||||
|
||||
$('#setAll').click(function(){
|
||||
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});
|
||||
$.post("/plugins/run", args, function(g) {
|
||||
layer.close(e);
|
||||
|
||||
@@ -2032,7 +2032,7 @@ function wsTableErrorLogRequest(page){
|
||||
type: 1,
|
||||
title: "【"+res.domain + "】详情信息",
|
||||
area: '600px',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15 lib-box">\
|
||||
<div style="height:80px;"><table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
|
||||
@@ -2110,7 +2110,7 @@ laydate.render({
|
||||
$(this).removeClass('cur');
|
||||
});
|
||||
|
||||
var timeA = value.split('-')
|
||||
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")
|
||||
@@ -2193,12 +2193,37 @@ function wsTableLogRequest(page){
|
||||
args['search_uri'] = search_uri;
|
||||
|
||||
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){
|
||||
var rdata = $.parseJSON(rdata.data);
|
||||
var list = '';
|
||||
var data = rdata.data.data;
|
||||
|
||||
if (data.length > 0){
|
||||
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 += '<td>' + getLocalTime(data[i]['time'])+'</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>' + 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: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 += '</tr>';
|
||||
}
|
||||
@@ -2241,7 +2266,7 @@ function wsTableLogRequest(page){
|
||||
type: 1,
|
||||
title: "【"+res.domain + "】详情信息",
|
||||
area: '600px',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="pd15 lib-box">\
|
||||
<div style="height:80px;"><table class="table" style="border:#ddd 1px solid; margin-bottom:10px">\
|
||||
@@ -2264,6 +2289,8 @@ function wsTableLogRequest(page){
|
||||
</div>',
|
||||
});
|
||||
});
|
||||
|
||||
$('[data-toggle="tooltip"]').tooltip();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -2322,7 +2349,7 @@ var html = '<div>\
|
||||
<option value="8">搜搜</option>\
|
||||
<option value="9">Dnspod</option>\
|
||||
<option value="10">Yandex</option>\
|
||||
<option value="12">神马</option>\
|
||||
<option value="11">一搜</option>\
|
||||
<option value="12">其他</option>\
|
||||
</select>\
|
||||
<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
Executable
+29
@@ -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
|
||||
Executable
+18
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
Executable
+6
@@ -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
|
||||
|
||||
@@ -54,7 +54,7 @@ function modifyAuthPath() {
|
||||
type: 1,
|
||||
area: "500px",
|
||||
title: "修改安全入口",
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form bt-form pd20 pb70">\
|
||||
@@ -131,7 +131,7 @@ function setPassword(a) {
|
||||
type: 1,
|
||||
area: "290px",
|
||||
title: '修改密码',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<div class='bt-form pd20 pb70'>\
|
||||
@@ -187,7 +187,7 @@ function setUserName(a) {
|
||||
type: 1,
|
||||
area: "290px",
|
||||
title: '修改面板用户名',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<div class='bt-form pd20 pb70'>\
|
||||
@@ -238,7 +238,7 @@ function setPanelSSL(){
|
||||
<input type="checkbox" id="checkSSL" /><label style="font-weight: 400;margin: 3px 5px 0px;" for="checkSSL">我已了经解详情,并愿意承担风险</label>\
|
||||
<a target="_blank" class="btlink" href="https://www.bt.cn/bbs/thread-4689-1-1.html" style="float: right;">了解详情</a>\
|
||||
</p>';
|
||||
layer.confirm(msg,{title:'设置面板SSL',closeBtn:2,icon:3,area:'550px',cancel:function(){
|
||||
layer.confirm(msg,{title:'设置面板SSL',closeBtn:1,icon:3,area:'550px',cancel:function(){
|
||||
if(status == 0){
|
||||
$("#panelSSL").prop("checked",false);
|
||||
}
|
||||
@@ -302,7 +302,7 @@ function getPanelSSL(){
|
||||
type: 1,
|
||||
area: "600px",
|
||||
title: '自定义面板证书',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content:certBody
|
||||
|
||||
@@ -180,7 +180,7 @@ function setControl(act, value=false){
|
||||
|
||||
//清理记录
|
||||
function closeControl(){
|
||||
layer.confirm('您真的清空所有监控记录吗?',{title:'清空记录',icon:3,closeBtn:2}, function() {
|
||||
layer.confirm('您真的清空所有监控记录吗?',{title:'清空记录',icon:3,closeBtn:1}, function() {
|
||||
loadT = layer.msg('正在处理,请稍候...',{icon:16,time:0})
|
||||
$.post('/system/set_control','type=del',function(rdata){
|
||||
layer.close(loadT);
|
||||
|
||||
@@ -24,7 +24,7 @@ function getLogs(id){
|
||||
title:lan.crontab.task_log_title,
|
||||
area: ['60%','500px'],
|
||||
shadeClose:false,
|
||||
closeBtn:2,
|
||||
closeBtn:1,
|
||||
content:'<div class="setchmod bt-form pd20 pb70">'
|
||||
+'<pre id="crontab-log" style="overflow: auto; border: 0px none; line-height:23px;padding: 15px; margin: 0px; white-space: pre-wrap; height: 405px; background-color: rgb(51,51,51);color:#f1f1f1;border-radius:0px;font-family:"></pre>'
|
||||
+'<div class="bt-form-submit-btn" style="margin-top: 0px;">'
|
||||
@@ -93,7 +93,7 @@ function getCronData(page){
|
||||
|
||||
// 设置计划任务状态
|
||||
function setTaskStatus(id,status){
|
||||
var confirm = layer.confirm(status == '0'?'计划任务暂停后将无法继续运行,您真的要停用这个计划任务吗?':'该计划任务已停用,是否要启用这个计划任务', {title:'提示',icon:3,closeBtn:2},function(index) {
|
||||
var confirm = layer.confirm(status == '0'?'计划任务暂停后将无法继续运行,您真的要停用这个计划任务吗?':'该计划任务已停用,是否要启用这个计划任务', {title:'提示',icon:3,closeBtn:1},function(index) {
|
||||
if (index > 0) {
|
||||
var loadT = layer.msg('正在设置状态,请稍后...',{icon:16,time:0,shade: [0.3, '#000']});
|
||||
$.post('/crontab/set_cron_status',{id:id},function(rdata){
|
||||
@@ -610,7 +610,7 @@ function editTaskInfo(id){
|
||||
area: ['850px','450px'],
|
||||
skin:'layer-create-content',
|
||||
shadeClose:false,
|
||||
closeBtn:2,
|
||||
closeBtn:1,
|
||||
content:'<div class="setting-con ptb20">\
|
||||
<div class="clearfix plan ptb10">\
|
||||
<span class="typename c4 pull-left f14 text-right mr20">任务类型</span>\
|
||||
|
||||
+10
-10
@@ -196,7 +196,7 @@ function recycleBin(type){
|
||||
layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
area: ['80%','606px'],
|
||||
title: lan.files.recycle_bin_title,
|
||||
content: tablehtml
|
||||
@@ -841,7 +841,7 @@ function createFile(type, path) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
area: '320px',
|
||||
title: '新建空白文件',
|
||||
content: '<div class="bt-form pd20 pb70">\
|
||||
@@ -881,7 +881,7 @@ function createDir(type, path) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
area: '320px',
|
||||
title: '新建目录',
|
||||
content: '<div class="bt-form pd20 pb70">\
|
||||
@@ -981,7 +981,7 @@ function downloadFile(action){
|
||||
layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
area: '500px',
|
||||
btn:["确定","关闭"],
|
||||
title: lan.files.down_title,
|
||||
@@ -1034,7 +1034,7 @@ function reName(type, fileName) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
area: '320px',
|
||||
title: '重命名',
|
||||
btn:["确定","保存"],
|
||||
@@ -1185,7 +1185,7 @@ function zip(dirName,submits) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
area: '650px',
|
||||
title: lan.files.zip_title,
|
||||
content: '<div class="bt-form pd20 pb70">'
|
||||
@@ -1241,7 +1241,7 @@ function unZip(fileName,type) {
|
||||
layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
area: '490px',
|
||||
title: '解压文件',
|
||||
content: '<div class="bt-form pd20 pb70">'
|
||||
@@ -1299,7 +1299,7 @@ function getImage(fileName){
|
||||
var imgUrl = '/files/download?filename='+fileName;
|
||||
layer.open({
|
||||
type:1,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
title:false,
|
||||
area: '500px',
|
||||
shadeClose: true,
|
||||
@@ -1319,7 +1319,7 @@ function uploadFiles(){
|
||||
var path = $("#DirPathPlace input").val()+"/";
|
||||
layer.open({
|
||||
type:1,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
title:lan.files.up_title,
|
||||
area: ['500px','300px'],
|
||||
shadeClose:false,
|
||||
@@ -1364,7 +1364,7 @@ function setChmod(action,fileName){
|
||||
// console.log(rdata);
|
||||
layer.open({
|
||||
type:1,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
title: '设置权限['+fileName+']',
|
||||
area: '400px',
|
||||
shadeClose:false,
|
||||
|
||||
@@ -527,7 +527,7 @@ function checkUpdate() {
|
||||
}
|
||||
|
||||
if (rdata.status === false) {
|
||||
layer.confirm(rdata.msg, { title: lan.index.update_check, icon: 1, closeBtn: 2, btn: [lan.public.know, lan.public.close] });
|
||||
layer.confirm(rdata.msg, { title: lan.index.update_check, icon: 1, closeBtn: 1, btn: [lan.public.know, lan.public.close] });
|
||||
return;
|
||||
}
|
||||
layer.msg(rdata.msg, { icon: 1 });
|
||||
@@ -610,7 +610,7 @@ function reBoot() {
|
||||
type: 1,
|
||||
title: '重启服务器或者面板',
|
||||
area: '330px',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="rebt-con"><div class="rebt-li"><a data-id="server" href="javascript:;">重启服务器</a></div><div class="rebt-li"><a data-id="panel" href="javascript:;">重启面板</a></div></div>'
|
||||
});
|
||||
@@ -620,7 +620,7 @@ function reBoot() {
|
||||
var type = $(this).attr('data-id');
|
||||
switch (type) {
|
||||
case 'panel':
|
||||
layer.confirm('即将重启面板服务,继续吗?', { title: '重启面板服务', closeBtn: 2, icon: 3 }, function () {
|
||||
layer.confirm('即将重启面板服务,继续吗?', { title: '重启面板服务', closeBtn: 1, icon: 3 }, function () {
|
||||
var loadT = layer.load();
|
||||
$.post('/system/restart','',function (rdata) {
|
||||
layer.close(loadT);
|
||||
@@ -634,7 +634,7 @@ function reBoot() {
|
||||
type: 1,
|
||||
title: '安全重启服务器',
|
||||
area: ['500px', '280px'],
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: "<div class='bt-form bt-window-restart'>\
|
||||
<div class='pd15'>\
|
||||
@@ -692,7 +692,7 @@ function reBoot() {
|
||||
|
||||
//修复面板
|
||||
function repPanel() {
|
||||
layer.confirm(lan.index.rep_panel_msg, { title: lan.index.rep_panel_title, closeBtn: 2, icon: 3 }, function() {
|
||||
layer.confirm(lan.index.rep_panel_msg, { title: lan.index.rep_panel_title, closeBtn: 1, icon: 3 }, function() {
|
||||
var loadT = layer.msg(lan.index.rep_panel_the, { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.get('/system?action=RepPanel', function(rdata) {
|
||||
layer.close(loadT);
|
||||
@@ -750,7 +750,7 @@ function showDanger(num, port) {
|
||||
type: 1,
|
||||
area: ['720px', '410px'],
|
||||
title: '安全提醒(如你想放弃任何安全提醒通知,请删除宝塔安全登录插件)',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
content: '<div class="pd20">\
|
||||
<table class="f14 showDanger"><tbody>\
|
||||
@@ -769,7 +769,7 @@ function showDanger(num, port) {
|
||||
//加载关键数据总数
|
||||
loadKeyDataCount();
|
||||
function loadKeyDataCount(){
|
||||
var plist = ['mysql', 'csvn', 'gogs'];
|
||||
var plist = ['mysql', 'gogs','gitea'];
|
||||
for (var i = 0; i < plist.length; i++) {
|
||||
pname = plist[i];
|
||||
function call(pname){
|
||||
@@ -784,7 +784,7 @@ function loadKeyDataCount(){
|
||||
}
|
||||
var html = '<li class="sys-li-box col-xs-3 col-sm-3 col-md-3 col-lg-3">\
|
||||
<p class="name f15 c9">'+pname+'</p>\
|
||||
<div class="val"><a class="btlink" onclick="softMain(\''+pname+'\',\''+rdata['data']['ver']+'\')">'+rdata['data']['count']+'</a></div></li>';
|
||||
<div class="val"><a class="btlink" onclick="softMain(\''+pname+'\',\''+pname+'\',\''+rdata['data']['ver']+'\')">'+rdata['data']['count']+'</a></div></li>';
|
||||
$('#index_overview').append(html);
|
||||
},'json');
|
||||
}
|
||||
|
||||
@@ -204,7 +204,7 @@ function changePath(d) {
|
||||
type: 1,
|
||||
area: "650px",
|
||||
title: '选择目录',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<div class='changepath'><div class='path-top'><button type='button' class='btn btn-default btn-sm' onclick='backFile()'><span class='glyphicon glyphicon-share-alt'></span>返回</button>\
|
||||
@@ -554,7 +554,7 @@ function onlineEditFile(k, f) {
|
||||
var r = layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
area: ["90%", "90%"],
|
||||
title: lan.bt.edit_title+"[" + f + "]",
|
||||
content: '<form class="bt-form pd20 pb70"><div class="line"><p style="color:red;margin-bottom:10px">'+lan.bt.edit_ps+' <select class="bt-input-text" name="encoding" style="width: 74px;position: absolute;top: 31px;right: 19px;height: 22px;z-index: 9999;border-radius: 0;">' + n + '</select></p><textarea class="mCustomScrollbar bt-input-text" id="textBody" style="width:100%;margin:0 auto;line-height: 1.8;position: relative;top: 10px;" value="" /> </div> <div class="bt-form-submit-btn" style="position:absolute; bottom:0; width:100%"> <button type="button" class="btn btn-danger btn-sm btn-editor-close">'+lan.public.close+'</button> <button id="OnlineEditFileBtn" type="button" class="btn btn-success btn-sm">'+lan.public.save+'</button> </div> </form>'
|
||||
@@ -638,7 +638,7 @@ function safeMessage(j, h, g, f) {
|
||||
type: 1,
|
||||
title: j,
|
||||
area: "350px",
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: true,
|
||||
content: "<div class='bt-form webDelete pd20 pb70'><p>" + h + "</p>" + f + "<div class='vcode'>"+lan.bt.cal_msg+"<span class='text'>" + sumtext + "</span>=<input type='number' id='vcodeResult' value=''></div><div class='bt-form-submit-btn'><button type='button' class='btn btn-danger btn-sm bt-cancel'>"+lan.public.cancel+"</button> <button type='button' id='toSubmit' class='btn btn-success btn-sm' >"+lan.public.ok+"</button></div></div>"
|
||||
});
|
||||
@@ -718,7 +718,7 @@ $(function() {
|
||||
});
|
||||
|
||||
$("#dologin").click(function() {
|
||||
layer.confirm('您真的要退出面板吗?', {icon:3,closeBtn: 2}, function() {
|
||||
layer.confirm('您真的要退出面板吗?', {icon:3,closeBtn: 1}, function() {
|
||||
window.location.href = "/login?dologin=True"
|
||||
});
|
||||
return false
|
||||
@@ -1030,7 +1030,7 @@ function bindPanel(a,type,ip,btid,url,user,pw){
|
||||
type: 1,
|
||||
area: "400px",
|
||||
title: titleName,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<div class='bt-form pd20 pb70'>\
|
||||
@@ -1106,7 +1106,7 @@ function messageBox() {
|
||||
type: 1,
|
||||
title: '消息盒子',
|
||||
area: "670px",
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="bt-form">\
|
||||
<div class="bt-w-main">\
|
||||
@@ -1459,7 +1459,7 @@ function webShell() {
|
||||
type: 1,
|
||||
title: "本地终端",
|
||||
area: ['685px','435px'],
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: false,
|
||||
content: '<div class="term-box"><div id="term"></div></div>\
|
||||
<div class="shell-text-input">\
|
||||
@@ -1661,7 +1661,7 @@ function pluginOpService(a, b, v) {
|
||||
case "restart":d = '重启';break;
|
||||
case "reload":d = '重载';break;
|
||||
}
|
||||
layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,v]), {icon:3,closeBtn: 2}, function() {
|
||||
layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,v]), {icon:3,closeBtn: 1}, function() {
|
||||
var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,v]), {icon: 16,time: 0});
|
||||
$.post("/plugins/run", c, function(g) {
|
||||
layer.close(e);
|
||||
@@ -1937,7 +1937,7 @@ function pluginOpInitD(a, _version, b) {
|
||||
case "initd_install":d = '加载';break;
|
||||
case "initd_uninstall":d = '卸载';break;
|
||||
}
|
||||
layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,_version]), {icon:3,closeBtn: 2}, function() {
|
||||
layer.confirm( msgTpl('您真的要{1}{2}{3}服务吗?', [d,a,_version]), {icon:3,closeBtn: 1}, function() {
|
||||
var e = layer.msg(msgTpl('正在{1}{2}{3}服务,请稍候...',[d,a,_version]), {icon: 16,time: 0});
|
||||
$.post("/plugins/run", c, function(g) {
|
||||
layer.close(e);
|
||||
|
||||
+14
-14
@@ -233,7 +233,7 @@ function webAddPage(type) {
|
||||
skin: 'demo-class',
|
||||
area: '640px',
|
||||
title: '添加网站',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 0,
|
||||
shadeClose: false,
|
||||
content: "<form class='bt-form pd20 pb70' id='addweb'>\
|
||||
@@ -673,7 +673,7 @@ function DomainRoot(id, name,msg) {
|
||||
skin: 'demo-class',
|
||||
area: '450px',
|
||||
title: lan.site.domain_man,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 0,
|
||||
shadeClose: true,
|
||||
content: "<div class='divtable padding-10'>\
|
||||
@@ -869,7 +869,7 @@ function getBackup(id,name,page) {
|
||||
skin: 'demo-class',
|
||||
area: '700px',
|
||||
title: '打包备份',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 0,
|
||||
shadeClose: false,
|
||||
content: "<div class='bt-form ptb15 mlr15' id='webBackup'>\
|
||||
@@ -918,7 +918,7 @@ function setIndex(id){
|
||||
type: 1,
|
||||
area: '500px',
|
||||
title: lan.site.setindex,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: true,
|
||||
content:"<form class='bt-form' id='SetIndex'><div class='SetIndex'>"
|
||||
@@ -964,7 +964,7 @@ function getDefaultSite(){
|
||||
type: 1,
|
||||
area: '530px',
|
||||
title: '设置默认站点',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: true,
|
||||
content:'<div class="bt-form ptb15 pb70">\
|
||||
@@ -1021,7 +1021,7 @@ function webEdit(id,website,endTime,addtime){
|
||||
type: 1,
|
||||
area: '640px',
|
||||
title: '站点修改['+website+'] -- 添加时间['+addtime+']',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 0,
|
||||
content: "<div class='bt-form'>"
|
||||
+"<div class='bt-w-menu pull-left' style='height: 565px;'>"
|
||||
@@ -1363,7 +1363,7 @@ function showRewrite(rdata){
|
||||
type: 1,
|
||||
area: '500px',
|
||||
title: '配置伪静态规则',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: true,
|
||||
content:webBakHtml
|
||||
@@ -1430,7 +1430,7 @@ function to301(siteName, type, obj){
|
||||
skin: 'demo-class',
|
||||
area: '650px',
|
||||
title: type == 1 ? '创建重定向' : '修改重定向[' + obj.redirectname + ']',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: "<form id='form_redirect' class='divtable pd20' style='padding-bottom: 60px'>" +
|
||||
@@ -1632,7 +1632,7 @@ function toProxy(siteName, type, obj) {
|
||||
type: 1,
|
||||
area: '650px',
|
||||
title: "创建反向代理",
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
btn: ['提交','关闭'],
|
||||
@@ -2381,7 +2381,7 @@ function setRewriteTel(act){
|
||||
aindex = layer.open({
|
||||
type: 1,
|
||||
shift: 5,
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
area: '320px', //宽高
|
||||
title: '保存为Rewrite模板',
|
||||
content: '<div class="bt-form pd20 pb70">\
|
||||
@@ -2408,7 +2408,7 @@ function siteDefaultPage(){
|
||||
type: 1,
|
||||
area: '460px',
|
||||
title: '修改默认页',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 0,
|
||||
content: '<div class="changeDefault pd20">\
|
||||
<button class="btn btn-default btn-sm mg10" style="width:188px" onclick="changeDefault(1)">默认文档</button>\
|
||||
@@ -2465,7 +2465,7 @@ function setClassType(){
|
||||
type: 1,
|
||||
area: '350px',
|
||||
title: '网站分类管理',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 0,
|
||||
content: '<div class="bt-form edit_site_type">\
|
||||
<div class="divtable mtb15" style="overflow:auto">\
|
||||
@@ -2523,7 +2523,7 @@ function editClassType(id,name){
|
||||
type: 1,
|
||||
area: '350px',
|
||||
title: '修改分类管理【' + name + '】',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 0,
|
||||
content: "<form class='bt-form bt-form pd20 pb70' id='mod_pwd'>\
|
||||
<div class='line'>\
|
||||
@@ -2563,7 +2563,7 @@ function moveClassTYpe(){
|
||||
type: 1,
|
||||
area: '350px',
|
||||
title: '设置站点分类',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 0,
|
||||
content: '<div class="bt-form edit_site_type">\
|
||||
<div class="divtable mtb15" style="overflow:auto;height:80px;">\
|
||||
|
||||
+23
-21
@@ -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> | ';
|
||||
// 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"';
|
||||
|
||||
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) {
|
||||
var option = '';
|
||||
var titlename = name;
|
||||
var titlename = title.replace("-"+ver,"");
|
||||
if (ver.indexOf('|') >= 0){
|
||||
var veropt = ver.split("|");
|
||||
var selectVersion = '';
|
||||
@@ -198,14 +198,14 @@ function addVersion(name, ver, type, obj, title, install_pre_inspection) {
|
||||
}
|
||||
option = "<select id='selectVersion' class='bt-input-text' style='margin-left:30px'>" + selectVersion + "</select>";
|
||||
} else {
|
||||
option = '<span id="selectVersion">' + name + ' ' + ver + '</span>';
|
||||
option = '<span id="selectVersion" val="' + name + ' ' + ver + '">【' + titlename + '】 ' + ver + '</span>';
|
||||
}
|
||||
|
||||
layer.open({
|
||||
type: 1,
|
||||
title: titlename + "软件安装",
|
||||
title: "【"+titlename + "】软件安装",
|
||||
area: '350px',
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shadeClose: true,
|
||||
btn: ['提交','关闭'],
|
||||
content: "<div class='bt-form pd20 c6'>\
|
||||
@@ -218,27 +218,28 @@ function addVersion(name, ver, type, obj, title, install_pre_inspection) {
|
||||
installTips();
|
||||
},
|
||||
yes:function(index,layero){
|
||||
// console.log(index,layero)
|
||||
var info = $("#selectVersion").val().toLowerCase();
|
||||
if (info == ''){
|
||||
info = $("#selectVersion").text().toLowerCase();
|
||||
info = $("#selectVersion").attr('val').toLowerCase();
|
||||
}
|
||||
var name = info.split(" ")[0];
|
||||
var version = info.split(" ")[1];
|
||||
var info_split = info.split(' ');
|
||||
var name = info_split[0];
|
||||
var version = info_split[1];
|
||||
|
||||
var type = $('.fangshi').prop("checked") ? '1' : '0';
|
||||
var data = "name=" + name + "&version=" + version + "&type=" + type;
|
||||
// console.log(data);
|
||||
var request_args = "name=" + name + "&version=" + version + "&type=" + type;
|
||||
|
||||
if (install_pre_inspection){
|
||||
//安装检查
|
||||
installPreInspection(name, version, function(){
|
||||
runInstall(data);
|
||||
runInstall(request_args);
|
||||
flySlow('layui-layer-btn0');
|
||||
});
|
||||
return;
|
||||
}
|
||||
runInstall(data);
|
||||
|
||||
runInstall(request_args);
|
||||
flySlow('layui-layer-btn0');
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -261,8 +262,9 @@ function uninstallPreInspection(name, ver, callback){
|
||||
}
|
||||
|
||||
|
||||
function runUninstallVersion(name, version){
|
||||
layer.confirm(msgTpl('您真的要卸载[{1}-{2}]吗?', [name, version]), { icon: 3, closeBtn: 2 }, function() {
|
||||
function runUninstallVersion(name, title, version){
|
||||
var title = title.replace("-"+version,"");
|
||||
layer.confirm(msgTpl('您真的要卸载【{1}-{2}】吗?', [title, version]), { icon: 3, closeBtn: 1 }, function() {
|
||||
var data = 'name=' + name + '&version=' + version;
|
||||
var loadT = layer.msg('正在处理,请稍候...', { icon: 16, time: 0, shade: [0.3, '#000'] });
|
||||
$.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) {
|
||||
uninstallPreInspection(name,version,function(){
|
||||
runUninstallVersion(name,version);
|
||||
uninstallPreInspection(name,title,version,function(){
|
||||
runUninstallVersion(name,title,version);
|
||||
});
|
||||
return;
|
||||
}
|
||||
runUninstallVersion(name,version);
|
||||
runUninstallVersion(name,title,version);
|
||||
}
|
||||
|
||||
|
||||
@@ -431,7 +433,7 @@ function importPlugin(file){
|
||||
type: 1,
|
||||
area: "500px",
|
||||
title: "安装第三方插件包",
|
||||
closeBtn: 2,
|
||||
closeBtn: 1,
|
||||
shift: 5,
|
||||
shadeClose: false,
|
||||
content: '<style>\
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user