diff --git a/README.md b/README.md index 22f45d10b..ae56efa69 100644 --- a/README.md +++ b/README.md @@ -90,16 +90,15 @@ 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.13 + +* 优化弹框。 +* 修复计划任务[日志切割]。 +* 优化mysql的与phpmyadmin的连接。 +* PHP添加`会话管理`功能。 +* redis优化。 +* 更新mysql[5.7]的安装。 +* OP防火墙部分功能优化。 ### JSDelivr安装地址 diff --git a/class/core/config_api.py b/class/core/config_api.py index c3b4c6a42..290ef4c6d 100755 --- a/class/core/config_api.py +++ b/class/core/config_api.py @@ -15,7 +15,7 @@ from flask import request class config_api: - __version = '0.9.12' + __version = '0.9.13' def __init__(self): pass diff --git a/plugins/clean/index.py b/plugins/clean/index.py index 3d2f0e8a6..f86ce26c8 100755 --- a/plugins/clean/index.py +++ b/plugins/clean/index.py @@ -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): diff --git a/plugins/clean/install.sh b/plugins/clean/install.sh index 25c89387b..c8cfe95d5 100755 --- a/plugins/clean/install.sh +++ b/plugins/clean/install.sh @@ -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 diff --git a/plugins/clean/tool_task.py b/plugins/clean/tool_task.py index be7868365..e7f27e86a 100644 --- a/plugins/clean/tool_task.py +++ b/plugins/clean/tool_task.py @@ -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" diff --git a/plugins/mariadb/js/mariadb.js b/plugins/mariadb/js/mariadb.js index 2299a0774..7e20b765a 100755 --- a/plugins/mariadb/js/mariadb.js +++ b/plugins/mariadb/js/mariadb.js @@ -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']}); diff --git a/plugins/mysql/js/mysql.js b/plugins/mysql/js/mysql.js index 374f8ef9e..fa86d71f3 100755 --- a/plugins/mysql/js/mysql.js +++ b/plugins/mysql/js/mysql.js @@ -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(){ diff --git a/plugins/mysql/versions/5.7/install.sh b/plugins/mysql/versions/5.7/install.sh index 072cff7c7..e3dac9c40 100755 --- a/plugins/mysql/versions/5.7/install.sh +++ b/plugins/mysql/versions/5.7/install.sh @@ -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() @@ -68,7 +68,7 @@ Install_mysql() fi #检测文件是否损坏. - md5_mysql_ok=d0489fc3880248a58759c50bfb286dbb + md5_mysql_ok=db1b672fc257bd46356c7af26dd22801 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 diff --git a/plugins/op_waf/conf/luawaf.conf b/plugins/op_waf/conf/luawaf.conf index 985cfca01..336df56a1 100755 --- a/plugins/op_waf/conf/luawaf.conf +++ b/plugins/op_waf/conf/luawaf.conf @@ -1,6 +1,6 @@ lua_shared_dict limit 30m; -lua_shared_dict drop_ip 30m; -lua_shared_dict drop_sum 30m; +lua_shared_dict drop_ip 10m; +lua_shared_dict drop_sum 10m; lua_package_path "{$WAF_PATH}/lua/?.lua;{$ROOT_PATH}/openresty/lualib/?.lua;;"; access_by_lua_file {$WAF_PATH}/lua/init.lua; diff --git a/plugins/op_waf/index.html b/plugins/op_waf/index.html index 9eff3b70c..fd718fbc9 100755 --- a/plugins/op_waf/index.html +++ b/plugins/op_waf/index.html @@ -232,7 +232,7 @@

全局配置

站点配置

封锁历史

- +

操作日志

diff --git a/plugins/op_waf/index.py b/plugins/op_waf/index.py index 2577aebec..b064dd07f 100755 --- a/plugins/op_waf/index.py +++ b/plugins/op_waf/index.py @@ -111,7 +111,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'] @@ -122,7 +122,22 @@ def initSiteInfo(): tmp['scan'] = config_contents['scan'] 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', + '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 +178,7 @@ def initTotalInfo(): tmp['get'] = 0 tmp['post'] = 0 tmp['total'] = 0 + tmp['url_ext'] = 0 _name = {} _name[name] = tmp total_contents['sites'] = _name @@ -186,10 +202,12 @@ 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 @@ -201,6 +219,14 @@ def initDreplace(): 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 +240,11 @@ 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) + waf_conf = mw.getServerDir() + "/openresty/nginx/conf/luawaf.conf" waf_tpl = getPluginDir() + "/conf/luawaf.conf" content = mw.readFile(waf_tpl) @@ -224,6 +255,9 @@ def initDreplace(): initSiteInfo() initTotalInfo() + if not mw.isAppleSystem(): + mw.execShell("chown -R www:www " + path) + def start(): initDreplace() @@ -800,7 +834,7 @@ def getLogsList(): return data[1] data = [] - path = mw.getLogsDir() + '/waf' + path = getServerDir() + '/logs' if not os.path.exists(path): return mw.returnJson(False, '还未生成!', []) @@ -823,7 +857,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, "文件不存在!") diff --git a/plugins/op_waf/install.sh b/plugins/op_waf/install.sh index 481fbd07c..35a36768a 100755 --- a/plugins/op_waf/install.sh +++ b/plugins/op_waf/install.sh @@ -19,12 +19,12 @@ Install_of(){ echo '0.1' > $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 } Uninstall_of(){ - cd ${rootPath} && python3 plugins/op_waf/index.py stop + cd ${rootPath} && python3 ${rootPath}/plugins/op_waf/index.py stop rm -rf $serverPath/op_waf } diff --git a/plugins/op_waf/js/op_waf.js b/plugins/op_waf/js/op_waf.js index d12fde0c9..da9650d8c 100755 --- a/plugins/op_waf/js/op_waf.js +++ b/plugins/op_waf/js/op_waf.js @@ -28,7 +28,7 @@ function setRequestCode(ruleName, statusCode){ title: "设置响应代码【" + ruleName + "】", area: '300px', shift: 5, - closeBtn: 2, + closeBtn: 1, shadeClose: true, content: '
\
\ @@ -144,7 +144,7 @@ function setCcRule(cycle, limit, endtime, siteName, increase){ type: 1, title: "设置CC规则", area: '540px', - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
\
\ @@ -184,7 +184,7 @@ function setRetry(retry_cycle, retry, retry_time, siteName) { type: 1, title: "设置恶意容忍规则", area: '500px', - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '\
\ @@ -339,7 +339,7 @@ function setObjConf(ruleName, type) { type: 1, title: "编辑规则【" + ruleName + "】", area: ['700px', '530px'], - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
\
\ @@ -405,7 +405,7 @@ function scanRule() { type: 1, title: "常用扫描器过滤规则", area: '650px', - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '\
\ @@ -571,7 +571,7 @@ function ipWhite(type) { type: 1, title: "管理IP白名单", area: ['500px', '500px'], - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
\
\ @@ -714,7 +714,7 @@ function ipBlack(type) { type: 1, title: "管理IP黑名单", area: ['500px', '500px'], - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
IPv4黑名单
IPv6黑名单
\
\ @@ -824,12 +824,12 @@ function wafScreen(){
CC攻击'+rdata.rules.cc+'
\
恶意User-Agent'+rdata.rules.user_agent+'
\
Cookie渗透'+rdata.rules.cookie+'
\ -
恶意扫描0
\ +
恶意扫描'+rdata.rules.scan+'
\
恶意HEAD请求0
\ -
URI自定义拦截0
\ -
URI保护0
\ +
URI自定义拦截'+rdata.rules.args+'
\ +
URI保护'+rdata.rules.args+'
\
恶意文件上传0
\ -
禁止的扩展名0
\ +
禁止的扩展名'+rdata.rules.url_ext+'
\
禁止PHP脚本0
\
'; @@ -975,7 +975,7 @@ function siteWafLog(siteName) { type: 1, title: "日志【" + siteName + "】", area: ['880px', '500px'], - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
\
\ @@ -1071,7 +1071,7 @@ function siteLogCon(siteName, day, page) { type: 1, title: time + "详情", area: '600px', - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
\ \ @@ -1190,7 +1190,7 @@ function siteRuleAdmin(siteName, ruleName, type) { type: 1, title: "管理网站过滤规则【" + title + "】", area: ['500px', '500px'], - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
\
\ @@ -1237,7 +1237,7 @@ function cdnHeader(siteName, type) { type: 1, title: "管理网站【" + siteName + "】CDN-Headers", area: ['500px', '500px'], - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
\
\ @@ -1342,7 +1342,7 @@ function setSiteObjConf(siteName, ruleName, type) { type: 1, title: "编辑网站【" + siteName + "】规则【" + ruleName + "】", area: ['700px', '530px'], - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
\
\ @@ -1394,7 +1394,7 @@ function siteWafConfig(siteName, type) { type: 1, title: "网站配置【" + siteName + "】", area: ['700px', '500px'], - closeBtn: 2, + closeBtn: 1, shadeClose: false, content: '
' }); diff --git a/plugins/op_waf/t/cc.py b/plugins/op_waf/t/cc.py deleted file mode 100644 index 3ad1ef97d..000000000 --- a/plugins/op_waf/t/cc.py +++ /dev/null @@ -1,7 +0,0 @@ -# coding:utf-8 - -import sys -import io -import os -import time -import json diff --git a/plugins/op_waf/t/index.py b/plugins/op_waf/t/index.py index b0cccb57a..2d2301d18 100644 --- a/plugins/op_waf/t/index.py +++ b/plugins/op_waf/t/index.py @@ -6,14 +6,168 @@ 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 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 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_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") -TEST_URL = "t1.cn" +def test_start(): + # test_Dir() + # test_UA() + # test_POST() + # test_scan() + # test_CC() + test_url_ext() -def run(): - print('op lua run ok') 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.1 && sh install.sh install 0.1') + os.system('cd /Users/midoks/Desktop/mwdev/server/mdserver-web/ && python3 plugins/openresty/index.py stop && python3 plugins/openresty/index.py start') + test_start() diff --git a/plugins/op_waf/t/test.sh b/plugins/op_waf/t/test.sh index 191618015..c614871c0 100755 --- a/plugins/op_waf/t/test.sh +++ b/plugins/op_waf/t/test.sh @@ -2,6 +2,8 @@ PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin export PATH +# yum -y install httpd-tools +# ab -c 1000 -n 1000000 http://xx.xx.xx/ python3 index.py diff --git a/plugins/op_waf/waf/config.json b/plugins/op_waf/waf/config.json index 92bbed594..c9835d484 100755 --- a/plugins/op_waf/waf/config.json +++ b/plugins/op_waf/waf/config.json @@ -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} \ No newline at end of file +{"reqfile_path": "{$WAF_PATH}/html", "retry": {"retry_time": 180, "is_open_global": 0, "retry": 6, "retry_cycle": 60}, "log": true, "scan": {"status": 444, "ps": "\u8fc7\u6ee4\u5e38\u89c1\u626b\u63cf\u6d4b\u8bd5\u5de5\u5177\u7684\u6e17\u900f\u6d4b\u8bd5", "open": true, "reqfile": ""}, "cc": {"status": 444, "ps": "\u8fc7\u8651CC\u653b\u51fb", "limit": 120, "endtime": 300, "open": true, "reqfile": "", "cycle": 60}, "get": {"status": 403, "ps": "\u8fc7\u6ee4uri\u3001uri\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "get.html"}, "log_save": 30, "user-agent": {"status": 403, "ps": "\u901a\u5e38\u7528\u4e8e\u8fc7\u6ee4\u6d4f\u89c8\u5668\u3001\u8718\u86db\u53ca\u4e00\u4e9b\u81ea\u52a8\u626b\u63cf\u5668", "open": true, "reqfile": "user_agent.html"}, "other": {"status": 403, "ps": "\u5176\u5b83\u975e\u901a\u7528\u8fc7\u6ee4", "reqfile": "other.html"}, "cookie": {"status": 403, "ps": "\u8fc7\u6ee4\u5229\u7528Cookie\u53d1\u8d77\u7684\u6e17\u900f\u653b\u51fb", "open": true, "reqfile": "cookie.html"}, "logs_path": "/www/wwwlogs/waf", "post": {"status": 403, "ps": "\u8fc7\u6ee4POST\u53c2\u6570\u4e2d\u5e38\u89c1sql\u6ce8\u5165\u3001xss\u7b49\u653b\u51fb", "open": true, "reqfile": "post.html"}, "open": true} \ No newline at end of file diff --git a/plugins/op_waf/waf/lua/common.lua b/plugins/op_waf/waf/lua/common.lua index f04c1686b..ed2c20b2e 100644 --- a/plugins/op_waf/waf/lua/common.lua +++ b/plugins/op_waf/waf/lua/common.lua @@ -1,26 +1,89 @@ local setmetatable = setmetatable -local _M = { _VERSION = '0.01' } +local _M = { _VERSION = '0.02' } local mt = { __index = _M } + local json = require "cjson" local ngx_match = ngx.re.find +local debug_mode = false + +local waf_root = "{$WAF_ROOT}" +local cpath = waf_root.."/waf/" +local logdir = waf_root.."/logs/" +local rpath = cpath.."/rule/" + +function _M.new(self) -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 + + local self = { + waf_root = waf_root, + cpath = cpath, + rpath = rpath, + logdir = logdir, + config = '', + site_config = '', + server_name = '', + params = nil } - local p = setmetatable(opt, mt) - return p + + return setmetatable(self, mt) +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") + 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 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 @@ -94,6 +157,10 @@ function _M.compare_ip(self,ips) end +function _M.to_json(self, msg) + return json.encode(msg) +end + function _M.return_message(self, status, msg) ngx.header.content_type = "application/json;" ngx.status = status @@ -136,20 +203,15 @@ function _M.write_file(self, filename, body) return true 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 filename = self.logdir .. 'drop_ip.log' + local fp = io.open(filename,'ab') local server_name = self.params["server_name"] local ip = self.params["server_name"] @@ -234,11 +296,21 @@ function _M.read_file(self, name) end function _M.read_file_table( self, name ) - return self:select_rule(self:read_file('args')) + return self:select_rule(self:read_file(name)) end +local function timer_at_inc_log(premature) + local total_path = cpath .. 'total.json' + local tbody = ngx.shared.limit:get(total_path) + if not tbody then + return false + end + return write_file_clear(total_path,tbody) +end + function _M.inc_log(self, name, rule) + local server_name = self.params['server_name'] local total_path = self.cpath .. 'total.json' local tbody = ngx.shared.limit:get(total_path) @@ -246,7 +318,10 @@ function _M.inc_log(self, name, rule) tbody = self:read_file_body(total_path) if not tbody then return false end end + local total = json.decode(tbody) + + -- 开始计算 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,13 +331,15 @@ 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.timer.at(1, timer_at_inc_log) + end @@ -289,9 +366,66 @@ function _M.get_server_name(self) end --- function _M.get_sn(self) --- retun string.gsub(self:get_server_name(),'_','.') --- end + +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 + + +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) + 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_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 +end function _M.is_ngx_match(self, rules, sbody, rule_name) @@ -341,6 +475,7 @@ 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'] @@ -352,6 +487,7 @@ function _M.write_log(self, name, rule) else ngx.shared.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 error_rule then @@ -384,10 +520,13 @@ end function _M.get_client_ip(self) local client_ip = "unknown" + local server_name = self.params['server_name'] + -- self:D("fff..."..client_ip..server_name) 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']) do + -- C:D("vv:"..v..tostring(request_header[v])) 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 @@ -408,7 +547,6 @@ end function _M.is_site_config(self,cname) - local server_name = self.params["server_name"] if self.site_config[server_name] ~= nil then if cname == 'cc' then return self.site_config[server_name][cname]['open'] diff --git a/plugins/op_waf/waf/lua/init.lua b/plugins/op_waf/waf/lua/init.lua index f4311e7d9..b03727aab 100644 --- a/plugins/op_waf/waf/lua/init.lua +++ b/plugins/op_waf/waf/lua/init.lua @@ -1,65 +1,55 @@ - -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 __C = require "common" +local C = __C:new() + +local waf_root = "{$WAF_ROOT}" -config = C:read_file_body_decode(cpath .. 'config.json') -local site_config = C:read_file_body_decode(cpath .. 'site.json') +config = C:read_file_body_decode(waf_root.."/waf/"..'config.json') +local site_config = C:read_file_body_decode(waf_root.."/waf/"..'site.json') C:setConfData(config, site_config) --- 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 = 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') +local user_agent_rules = C:read_file('user_agent') +local post_rules = C:read_file('post') +local cookie_rules = C:read_file('cookie') + + +local server_name = string.gsub(C:get_server_name(),'_','.') + + +-- C:D("sss:"..C:get_server_name()) function initParams() local data = {} - data['ip'] = C:get_client_ip() - data['ipn'] = C:arrip(data['ip']) + data['server_name'] = server_name + -- data['ip'] = C:get_client_ip() + -- 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['cookie'] = ngx.var.http_cookie return data end local params = initParams() C:setParams(params) +C:setDebug(true) - +local server_name = params["server_name"] +params['ip'] = C:get_client_ip() +params['ipn'] = C:arrip(params['ip']) +C:D(server_name) function get_return_state(rstate,rmsg) result = {} @@ -102,20 +92,20 @@ function save_ip_on(data) end end -function remove_btwaf_drop_ip() +function remove_waf_drop_ip() if not uri_request_args['ip'] or not C:is_ipaddr(uri_request_args['ip']) then return get_return_state(true,'格式错误') end 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']) + 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) + 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 + v['time'] = 0 end end end @@ -125,7 +115,7 @@ function remove_btwaf_drop_ip() return get_return_state(true,uri_request_args['ip'] .. '已解封') end -function clean_btwaf_drop_ip() +function clean_waf_drop_ip() if ngx.shared.btwaf:get(cpath2 .. 'stop_ip') then ret2=ngx.shared.btwaf:get(cpath2 .. 'stop_ip') ip_data2=json.decode(ret2) @@ -155,15 +145,7 @@ function min_route() 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() +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:write_log('args','regular') @@ -196,38 +178,55 @@ function waf_ip_black() end -function waf_drop() - local count,_ = ngx.shared.drop_ip:get(ip) - if not count then return false end - if count > config['retry'] then - ngx.exit(config['cc']['status']) +function waf_user_agent() + -- 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_ua(user_agent_rules,params['request_header']['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 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) +function waf_drop() + local count , _ = ngx.shared.drop_ip:get(ip) + if not count then return false end + if count > config['retry'] then + ngx.exit(config['cc']['status']) return true end return false end -function cc() +function waf_cc() local ip = params['ip'] + + local ip_lock = ngx.shared.drop_ip:get(ip) + if ip_lock then + if ip_lock > 0 then + ngx.exit(config['cc']['status']) + return true + end + end + + if not config['cc']['open'] or not C:is_site_config('cc') then return false end + + local request_uri = params['request_uri'] local endtime = config['cc']['endtime'] - if not config['cc']['open'] or not site_cc then return false end local token = ngx.md5(ip .. '_' .. request_uri) - local count,_ = ngx.shared.limit:get(token) + local count = ngx.shared.limit:get(token) + + local 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 > limit then + + local safe_count, _ = ngx.shared.drop_sum:get(ip) if not safe_count then ngx.shared.drop_sum:set(ip,1,86400) safe_count = 1 @@ -236,23 +235,22 @@ function cc() 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) + + -- lock_time = 10 + ngx.shared.drop_ip:set(ip,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.exit(config['cc']['status']) return true else ngx.shared.limit:incr(token,1) end else - ngx.shared.limit:set(token,1,cycle) + ngx.shared.drop_sum:set(ip,1,86400) + ngx.shared.limit:set(token, 1, cycle) end + return false end --强制验证是否使用正常浏览器访问网站 @@ -287,20 +285,25 @@ end 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 + 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:is_ngx_match(scan_black_rules['args'],params["request_uri"],false) then + + 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,20 +312,9 @@ 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() 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 if content_length > max_len then return false end @@ -333,7 +325,19 @@ function waf_post() return false end - if C:is_ngx_match(post_rules,request_args,'post') then + 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(post_rules,data) then C:write_log('post','regular') C:return_html(config['post']['status'],post_html) return true @@ -366,10 +370,11 @@ function post_data_chekc() end if not list_list then return false end - aaa=nil + + aaa = nil for k,v in pairs(request_args) do - aaa=v + aaa = v end if not aaa then return false end @@ -381,7 +386,7 @@ function post_data_chekc() 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 + if C:is_ngx_match_post(post_rules , data_len) then C:write_log('post','regular') C:return_html(config['post']['status'],post_html) return true @@ -406,7 +411,7 @@ end 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 C:is_ngx_match_post(post_rules,params["request_header"]['X-forwarded-For']) then C:write_log('post','regular') C:return_html(config['post']['status'],post_html) return true @@ -415,39 +420,39 @@ function post_X_Forwarded() 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 php_path() +-- if site_config[server_name] == nil then return false end +-- for _,rule in ipairs(site_config[server_name]['disable_php_path']) +-- do +-- if C:ngx_match_string(params['uri'],rule .. "/?.*\\.php$","isjo") then +-- C:write_log('php_path','regular') +-- C:return_html(config['other']['status'],other_html) +-- return C:return_message(200,uri) +-- end +-- end +-- return false +-- end + +-- function url_path() +-- if site_config[server_name] == nil then return false end +-- for _,rule in ipairs(site_config[server_name]['disable_path']) +-- do +-- if ngx_match(uri,rule,"isjo") then +-- C:write_log('path','regular') +-- C:return_html(config['other']['status'],other_html) +-- return true +-- end +-- end +-- return false +-- end function url_ext() if site_config[server_name] == nil then return false end for _,rule in ipairs(site_config[server_name]['disable_ext']) do - if ngx_match(uri,"\\."..rule.."$","isjo") then + if C:ngx_match_string("\\."..rule.."$", params['uri'],'url_ext') then C:write_log('url_ext','regular') - C:return_html(config['other']['status'],other_html) + C:return_html(config['other']['status'], other_html) return true end end @@ -555,7 +560,7 @@ function waf_cookie() 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 +568,45 @@ 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() - waf_url() + -- cc setting + if waf_drop() then return true end + if waf_cc() then return true end - if params["method"] == "GET" then - waf_referer() - waf_cookie() - end + -- ua check + if waf_user_agent() then return true end + if waf_url() then return true end - if params["method"] == "POST" then - waf_referer() - waf_cookie() - end - - waf_args() - waf_scan_black() + -- cookie检查 + if waf_cookie() then return true end + + -- args参数拦截 + if waf_get_args() then return true end - waf_post() - post_data_chekc() + -- 扫描软件禁止 + if waf_scan_black() then return true end - 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 post_data_chekc() then return true end + + if site_config[server_name]['open'] then + if X_Forwarded() then return true end + if post_X_Forwarded() then return true end + -- url_path() + if url_ext() then return true end + -- url_rule_ex() + -- url_tell() + -- post_data() end end diff --git a/plugins/op_waf/waf/rule/user_agent.json b/plugins/op_waf/waf/rule/user_agent.json index b85a8e35d..0f5c5318c 100755 --- a/plugins/op_waf/waf/rule/user_agent.json +++ b/plugins/op_waf/waf/rule/user_agent.json @@ -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]] \ No newline at end of file +[[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]] \ No newline at end of file diff --git a/plugins/op_waf/waf/total.json b/plugins/op_waf/waf/total.json index ca94ae3d3..4d111b7ed 100644 --- a/plugins/op_waf/waf/total.json +++ b/plugins/op_waf/waf/total.json @@ -1 +1 @@ -{"rules":{"user_agent":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0} \ No newline at end of file +{"rules":{"url_ext":0,"user_agent":0,"scan":0,"cookie":0,"post":0,"args":0,"url":0,"cc":0},"sites":{},"total":0} \ No newline at end of file diff --git a/plugins/php-apt/index.html b/plugins/php-apt/index.html index 790f56c06..654c500c0 100755 --- a/plugins/php-apt/index.html +++ b/plugins/php-apt/index.html @@ -1,3 +1,41 @@ + + +
@@ -13,6 +51,7 @@

禁用函数

性能调整

负载状况

+

会话管理

FPM日志

慢日志

PHPIFNO

diff --git a/plugins/php-apt/index.py b/plugins/php-apt/index.py index af7397d5e..f865e4ba9 100755 --- a/plugins/php-apt/index.py +++ b/plugins/php-apt/index.py @@ -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': diff --git a/plugins/php-apt/js/php.js b/plugins/php-apt/js/php.js index fd6e14003..9b20f6f98 100755 --- a/plugins/php-apt/js/php.js +++ b/plugins/php-apt/js/php.js @@ -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 = "" + + "" + + "" + + ""; + + + var info = rdata.save_path.split(":"); + var con = "
" + + "

存储模式:

" + + "

IP地址:

" + + "

端口:

" + + "

密码:

" + + "

" + + "
\ +
    \ +
  • 若你的站点并发比较高,使用Redis,Memcache能有效提升PHP并发能力
  • \ +
  • 若调整Session模式后,网站访问异常,请切换回原来的模式
  • \ +
  • 切换Session模式会使在线的用户会话丢失,请在流量小的时候切换
  • \ +
\ +
\ +
\ +
"; + + $(".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 = "
清理Session文件
\ +
\ +
\ +
总Session文件数量"+rdata.total+"
\ +
可清理的Session文件数量"+rdata.oldfile+"
\ +
\ + "; + + $("#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(','); diff --git a/plugins/php-yum/index.html b/plugins/php-yum/index.html index 3b4957222..878e98f41 100755 --- a/plugins/php-yum/index.html +++ b/plugins/php-yum/index.html @@ -1,3 +1,40 @@ + +
@@ -13,6 +50,7 @@

禁用函数

性能调整

负载状况

+

会话管理

FPM日志

慢日志

PHPIFNO

diff --git a/plugins/php-yum/index.py b/plugins/php-yum/index.py index e99c25867..a6595ab89 100755 --- a/plugins/php-yum/index.py +++ b/plugins/php-yum/index.py @@ -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': diff --git a/plugins/php-yum/js/php.js b/plugins/php-yum/js/php.js index e059e3a36..332158bbd 100755 --- a/plugins/php-yum/js/php.js +++ b/plugins/php-yum/js/php.js @@ -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 = "" + + "" + + "" + + ""; + + + var info = rdata.save_path.split(":"); + var con = "
" + + "

存储模式:

" + + "

IP地址:

" + + "

端口:

" + + "

密码:

" + + "

" + + "
\ +
    \ +
  • 若你的站点并发比较高,使用Redis,Memcache能有效提升PHP并发能力
  • \ +
  • 若调整Session模式后,网站访问异常,请切换回原来的模式
  • \ +
  • 切换Session模式会使在线的用户会话丢失,请在流量小的时候切换
  • \ +
\ +
\ +
\ +
"; + + $(".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 = "
清理Session文件
\ +
\ +
\ +
总Session文件数量"+rdata.total+"
\ +
可清理的Session文件数量"+rdata.oldfile+"
\ +
\ + "; + + $("#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){ diff --git a/plugins/php/index.html b/plugins/php/index.html index 05dd0c4ac..5ec54976c 100755 --- a/plugins/php/index.html +++ b/plugins/php/index.html @@ -1,6 +1,43 @@ + +
-
+

服务

自启动

@@ -13,6 +50,7 @@

禁用函数

性能调整

负载状况

+

会话管理

FPM日志

慢日志

PHPIFNO

@@ -24,6 +62,7 @@
+