From ebf474aefb505ff02bc0528fc3a4a789eb8118b2 Mon Sep 17 00:00:00 2001 From: Mr Chen Date: Thu, 31 Oct 2024 19:20:35 +0800 Subject: [PATCH] up --- plugins/tgbot/startup/extend/push_notice_msg.py | 2 +- web/admin/dashboard/__init__.py | 2 +- web/admin/firewall/__init__.py | 6 +- web/admin/setting/__init__.py | 153 +--------------------- web/admin/setting/main.py | 167 ++++++++++++++++++++++++ web/admin/setting/temp_login.py | 65 +++++++++ web/admin/soft/__init__.py | 4 +- web/static/app/config.js | 24 ++-- web/static/app/firewall.js | 8 +- web/utils/firewall.py | 110 ++++++++++++++++ web/utils/mwplugin.py | 1 - 11 files changed, 374 insertions(+), 168 deletions(-) create mode 100644 web/admin/setting/main.py create mode 100644 web/admin/setting/temp_login.py diff --git a/plugins/tgbot/startup/extend/push_notice_msg.py b/plugins/tgbot/startup/extend/push_notice_msg.py index 227eaa57f..0fea5ff39 100644 --- a/plugins/tgbot/startup/extend/push_notice_msg.py +++ b/plugins/tgbot/startup/extend/push_notice_msg.py @@ -52,7 +52,7 @@ def send_msg(bot, tag='ad', trigger_time=300): # https://t.me/gjgzs2022 | 22/m | @GJ_gzs # https://zhaoziyuan1.cc | web | 15/m | 2m | next,12/15 | @baleite - # 综合包网/NG接口开户 | 28/m | 6m | next,10/28 | x + # 综合包网/NG接口开户 | 28/m | 6m | next,4/28 | x # 实名认证/过人脸🕵️‍♀️各种账号处理✅ | 30/m| next,12/30 | @nngzs # 桃花资源采集| 13/m| next,1/13 | @xiaolizi1122 keyboard = [ diff --git a/web/admin/dashboard/__init__.py b/web/admin/dashboard/__init__.py index 2e37cfbdd..a31a3dc33 100644 --- a/web/admin/dashboard/__init__.py +++ b/web/admin/dashboard/__init__.py @@ -30,7 +30,7 @@ def index(): return render_template('default/index.html') # 仅针对webhook插件 -@app.route("/hook", methods=['POST', 'GET']) +@blueprint.route("/hook", methods=['POST', 'GET']) def webhook(): # 兼容获取关键数据 access_key = request.args.get('access_key', '').strip() diff --git a/web/admin/firewall/__init__.py b/web/admin/firewall/__init__.py index 9ed6f057e..c8dbf3728 100644 --- a/web/admin/firewall/__init__.py +++ b/web/admin/firewall/__init__.py @@ -15,6 +15,9 @@ from flask import request from admin.user_login_check import panel_login_required from admin.model import db, Firewall + +from utils.firewall import Firewall as MwFirewall + import core.mw as mw blueprint = Blueprint('firewall', __name__, url_prefix='/firewall', template_folder='../../templates/default') @@ -61,7 +64,8 @@ def get_www_path(): @blueprint.route('/get_ssh_info', endpoint='get_ssh_info', methods=['POST']) @panel_login_required def get_ssh_info(): - pass + mf = MwFirewall.instance() + return mf.getSshInfo() diff --git a/web/admin/setting/__init__.py b/web/admin/setting/__init__.py index 4b53d8604..25d4d3a78 100644 --- a/web/admin/setting/__init__.py +++ b/web/admin/setting/__init__.py @@ -8,157 +8,8 @@ # Author: midoks # --------------------------------------------------------------------------------- -import re -import json -import os - -from flask import Blueprint, render_template -from flask import request - -from admin import model -from admin.user_login_check import panel_login_required - -import core.mw as mw -import utils.config as utils_config - -# 默认页面 -blueprint = Blueprint('setting', __name__, url_prefix='/setting', template_folder='../../templates') -@blueprint.route('/index', endpoint='index') -@panel_login_required -def index(): - return render_template('default/setting.html') - -@blueprint.route('/get_panel_list', endpoint='get_panel_list', methods=['POST']) -@panel_login_required -def get_panel_list(): - return [] - - -# 设置面板名称 -@blueprint.route('/set_webname', endpoint='set_webname', methods=['POST']) -@panel_login_required -def set_webname(): - webname = request.form.get('webname', '') - src_webname = model.getOption('title') - if webname != src_webname: - model.setOption('title', webname) - return mw.returnData(True, '面板别名保存成功!') - -# 设置服务器IP -@blueprint.route('/set_ip', endpoint='set_ip', methods=['POST']) -@panel_login_required -def set_ip(): - host_ip = request.form.get('host_ip', '') - src_host_ip = model.getOption('server_ip') - if host_ip != src_host_ip: - model.setOption('server_ip', host_ip) - return mw.returnData(True, 'IP保存成功!') - -# 默认备份目录 -@blueprint.route('/set_backup_dir', endpoint='set_backup_dir', methods=['POST']) -@panel_login_required -def set_backup_dir(): - backup_path = request.form.get('backup_path', '') - src_backup_path = model.getOption('backup_path') - if backup_path != src_backup_path: - model.setOption('backup_path', backup_path) - return mw.returnData(True, '修改默认备份目录成功!') - -# 默认站点目录 -@blueprint.route('/set_www_dir', endpoint='set_www_dir', methods=['POST']) -@panel_login_required -def set_www_dir(): - sites_path = request.form.get('sites_path', '') - src_sites_path = model.getOption('sites_path') - if sites_path != src_sites_path: - model.setOption('sites_path', sites_path) - return mw.returnData(True, '修改默认建站目录成功!') - - -# 设置安全入口 -@blueprint.route('/set_admin_path', endpoint='set_admin_path', methods=['POST']) -@panel_login_required -def set_admin_path(): - admin_path = request.form.get('admin_path', '') - admin_path_sensitive = [ - '/', '/close', '/login', - '/do_login', '/site', '/sites', - '/download_file', '/control', '/crontab', - '/firewall', '/files', '/config', '/setting','/monitor' - '/soft', '/system', '/code', - '/ssl', '/plugins', '/hook' - ] - - if admin_path == '': - admin_path = '/' - - if admin_path != '/': - if len(admin_path) < 6: - return mw.returnData(False, '安全入口地址长度不能小于6位!') - if admin_path in admin_path_sensitive: - return mw.returnData(False, '该入口已被面板占用,请使用其它入口!') - if not re.match(r"^/[\w]+$", admin_path): - return mw.returnData(False, '入口地址格式不正确,示例: /mw_rand') - - src_admin_path = model.getOption('admin_path') - if admin_path != src_admin_path: - model.setOption('admin_path', admin_path[1:]) - return mw.returnData(True, '修改成功!') - - - -# 设置BasicAuth认证 -@blueprint.route('/set_basic_auth', endpoint='set_basic_auth', methods=['POST']) -@panel_login_required -def set_basic_auth(): - basic_user = request.form.get('basic_user', '').strip() - basic_pwd = request.form.get('basic_pwd', '').strip() - basic_open = request.form.get('is_open', '').strip() - - __file = mw.getCommonFile() - path = __file['basic_auth'] - - is_open = True - if basic_open == 'false': - is_open = False - - if basic_open == 'false': - model.setOption('basic_auth', json.dumps({'open':False})) - mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open) - return mw.returnData(True, '删除BasicAuth成功!') - - if basic_user == '' or basic_pwd == '': - return mw.returnData(False, '用户和密码不能为空!') - - salt = mw.getRandomString(6) - data = {} - data['salt'] = salt - data['basic_user'] = mw.md5(basic_user + salt) - data['basic_pwd'] = mw.md5(basic_pwd + salt) - data['open'] = is_open - - model.setOption('basic_auth', json.dumps(data)) - mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open) - return mw.returnData(True, '设置成功!') - - -# 默认站点目录 -@blueprint.route('/set_status_code', endpoint='set_status_code', methods=['POST']) -@panel_login_required -def set_status_code(): - status_code = request.form.get('status_code', '').strip() - if re.match(r"^\d+$", status_code): - status_code = int(status_code) - if status_code != 0: - if status_code < 100 or status_code > 999: - return mw.returnData(False, '状态码范围错误!!') - else: - return mw.returnData(False, '状态码范围错误!') - - info = utils_config.getUnauthStatus(code=str(status_code)) - model.setOption('unauthorized_status', str(status_code)) - mw.writeLog('面板设置', '将未授权响应状态码设置为:{0}:{1}'.format(status_code,info['text'])) - return mw.returnData(True, '设置成功!') +from .main import * +from .temp_login import * diff --git a/web/admin/setting/main.py b/web/admin/setting/main.py new file mode 100644 index 000000000..4b53d8604 --- /dev/null +++ b/web/admin/setting/main.py @@ -0,0 +1,167 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + +import re +import json +import os + +from flask import Blueprint, render_template +from flask import request + +from admin import model +from admin.user_login_check import panel_login_required + +import core.mw as mw +import utils.config as utils_config + +# 默认页面 +blueprint = Blueprint('setting', __name__, url_prefix='/setting', template_folder='../../templates') +@blueprint.route('/index', endpoint='index') +@panel_login_required +def index(): + return render_template('default/setting.html') + +@blueprint.route('/get_panel_list', endpoint='get_panel_list', methods=['POST']) +@panel_login_required +def get_panel_list(): + return [] + + +# 设置面板名称 +@blueprint.route('/set_webname', endpoint='set_webname', methods=['POST']) +@panel_login_required +def set_webname(): + webname = request.form.get('webname', '') + src_webname = model.getOption('title') + if webname != src_webname: + model.setOption('title', webname) + return mw.returnData(True, '面板别名保存成功!') + +# 设置服务器IP +@blueprint.route('/set_ip', endpoint='set_ip', methods=['POST']) +@panel_login_required +def set_ip(): + host_ip = request.form.get('host_ip', '') + src_host_ip = model.getOption('server_ip') + if host_ip != src_host_ip: + model.setOption('server_ip', host_ip) + return mw.returnData(True, 'IP保存成功!') + +# 默认备份目录 +@blueprint.route('/set_backup_dir', endpoint='set_backup_dir', methods=['POST']) +@panel_login_required +def set_backup_dir(): + backup_path = request.form.get('backup_path', '') + src_backup_path = model.getOption('backup_path') + if backup_path != src_backup_path: + model.setOption('backup_path', backup_path) + return mw.returnData(True, '修改默认备份目录成功!') + +# 默认站点目录 +@blueprint.route('/set_www_dir', endpoint='set_www_dir', methods=['POST']) +@panel_login_required +def set_www_dir(): + sites_path = request.form.get('sites_path', '') + src_sites_path = model.getOption('sites_path') + if sites_path != src_sites_path: + model.setOption('sites_path', sites_path) + return mw.returnData(True, '修改默认建站目录成功!') + + +# 设置安全入口 +@blueprint.route('/set_admin_path', endpoint='set_admin_path', methods=['POST']) +@panel_login_required +def set_admin_path(): + admin_path = request.form.get('admin_path', '') + admin_path_sensitive = [ + '/', '/close', '/login', + '/do_login', '/site', '/sites', + '/download_file', '/control', '/crontab', + '/firewall', '/files', '/config', '/setting','/monitor' + '/soft', '/system', '/code', + '/ssl', '/plugins', '/hook' + ] + + if admin_path == '': + admin_path = '/' + + if admin_path != '/': + if len(admin_path) < 6: + return mw.returnData(False, '安全入口地址长度不能小于6位!') + if admin_path in admin_path_sensitive: + return mw.returnData(False, '该入口已被面板占用,请使用其它入口!') + if not re.match(r"^/[\w]+$", admin_path): + return mw.returnData(False, '入口地址格式不正确,示例: /mw_rand') + + src_admin_path = model.getOption('admin_path') + if admin_path != src_admin_path: + model.setOption('admin_path', admin_path[1:]) + return mw.returnData(True, '修改成功!') + + + +# 设置BasicAuth认证 +@blueprint.route('/set_basic_auth', endpoint='set_basic_auth', methods=['POST']) +@panel_login_required +def set_basic_auth(): + basic_user = request.form.get('basic_user', '').strip() + basic_pwd = request.form.get('basic_pwd', '').strip() + basic_open = request.form.get('is_open', '').strip() + + __file = mw.getCommonFile() + path = __file['basic_auth'] + + is_open = True + if basic_open == 'false': + is_open = False + + if basic_open == 'false': + model.setOption('basic_auth', json.dumps({'open':False})) + mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open) + return mw.returnData(True, '删除BasicAuth成功!') + + if basic_user == '' or basic_pwd == '': + return mw.returnData(False, '用户和密码不能为空!') + + salt = mw.getRandomString(6) + data = {} + data['salt'] = salt + data['basic_user'] = mw.md5(basic_user + salt) + data['basic_pwd'] = mw.md5(basic_pwd + salt) + data['open'] = is_open + + model.setOption('basic_auth', json.dumps(data)) + mw.writeLog('面板设置', '设置BasicAuth状态为: %s' % is_open) + return mw.returnData(True, '设置成功!') + + +# 默认站点目录 +@blueprint.route('/set_status_code', endpoint='set_status_code', methods=['POST']) +@panel_login_required +def set_status_code(): + status_code = request.form.get('status_code', '').strip() + if re.match(r"^\d+$", status_code): + status_code = int(status_code) + if status_code != 0: + if status_code < 100 or status_code > 999: + return mw.returnData(False, '状态码范围错误!!') + else: + return mw.returnData(False, '状态码范围错误!') + + info = utils_config.getUnauthStatus(code=str(status_code)) + model.setOption('unauthorized_status', str(status_code)) + mw.writeLog('面板设置', '将未授权响应状态码设置为:{0}:{1}'.format(status_code,info['text'])) + return mw.returnData(True, '设置成功!') + + + + + + \ No newline at end of file diff --git a/web/admin/setting/temp_login.py b/web/admin/setting/temp_login.py new file mode 100644 index 000000000..b50714e62 --- /dev/null +++ b/web/admin/setting/temp_login.py @@ -0,0 +1,65 @@ +# coding:utf-8 + +# --------------------------------------------------------------------------------- +# MW-Linux面板 +# --------------------------------------------------------------------------------- +# copyright (c) 2018-∞(https://github.com/midoks/mdserver-web) All rights reserved. +# --------------------------------------------------------------------------------- +# Author: midoks +# --------------------------------------------------------------------------------- + +import re +import json +import os +import time + +from flask import Blueprint, render_template +from flask import request + +from admin import model +from admin.model import db,TempLogin +from admin.user_login_check import panel_login_required + +import core.mw as mw +import utils.config as utils_config + +from .main import blueprint + + +@blueprint.route('/set_temp_login', endpoint='set_temp_login', methods=['POST']) +@panel_login_required +def set_temp_login(): + # if 'tmp_login_expire' in session: + # return mw.returnData(False, '没有权限') + start_time = int(time.time()) + # mw.M('temp_login').where( + # 'state=? and expire>?', (0, start_time)).delete() + + + token = mw.getRandomString(48) + salt = mw.getRandomString(12) + + expire=start_time+3600 + make_token = mw.md5(token + salt) + add_tl = TempLogin( + token=make_token, + salt=salt, + state=0, + login_time=0, + login_addr='', + expire=expire, + add_time=start_time) + r = db.session.add(add_tl) + db.session.commit() + + + # if not mw.M('temp_login').count(): + # pdata['id'] = 101 + + # if mw.M('temp_login').insert(pdata): + # mw.writeLog('面板设置', '生成临时连接,过期时间:{}'.format(mw.formatDate(times=pdata['expire']))) + # return mw.getJson({'status': True, 'msg': "临时连接已生成", 'token': token, 'expire': pdata['expire']}) + return mw.returnData(False, '连接生成失败') + + + diff --git a/web/admin/soft/__init__.py b/web/admin/soft/__init__.py index 78569ce25..09a417826 100644 --- a/web/admin/soft/__init__.py +++ b/web/admin/soft/__init__.py @@ -13,8 +13,8 @@ from flask import Blueprint, render_template from admin.user_login_check import panel_login_required -blueprint = Blueprint('soft', __name__, url_prefix='/soft', template_folder='../../templates/default') +blueprint = Blueprint('soft', __name__, url_prefix='/soft', template_folder='../../templates') @blueprint.route('/index', endpoint='index') @panel_login_required def index(): - return render_template('soft.html') \ No newline at end of file + return render_template('default/soft.html') \ No newline at end of file diff --git a/web/static/app/config.js b/web/static/app/config.js index 989101bea..078a8c393 100755 --- a/web/static/app/config.js +++ b/web/static/app/config.js @@ -1170,29 +1170,33 @@ function setTempAccess(){ closeBtn:1, shift: 0, type: 1, - content: "
\ - \ -
\ - \ + content: "
\ \ - \ + \ + \ + \ + \ + \ + \ \ - \ + \
登录IP状态登录时间过期时间操作
登录IP状态登录时间过期时间操作
\ - \ + \
\
", success:function(){ setTempAccessReq(); $('.create_temp_login').click(function(){ - layer.confirm('注意1:滥用临时授权可能导致安全风险。
注意2:请勿在公共场合发布临时授权连接

即将创建临时授权连接,继续吗?', - { + layer.confirm('注意1:滥用临时授权可能导致安全风险。
注意2:请勿在公共场合发布临时授权连接

即将创建临时授权连接,继续吗?',{ title:'风险提示', closeBtn:1, icon:13, }, function(create_temp_login_layer) { - $.post('/config/set_temp_login', {}, function(rdata){ + $.post('/setting/set_temp_login', {}, function(rdata){ layer.close(create_temp_login_layer); setTempAccessReq(); layer.open({ diff --git a/web/static/app/firewall.js b/web/static/app/firewall.js index 19f7d6875..07f7230f1 100755 --- a/web/static/app/firewall.js +++ b/web/static/app/firewall.js @@ -119,7 +119,7 @@ function getSshInfo(){ } $("#firewall_status").html(fStatus); - showAccept(1); + // showAccept(1); },'json'); } @@ -306,6 +306,12 @@ function showAccept(page,search) { 删除\ "; } + + if (data.data.length == 0){ + body = '当前没有数据'; + } + + $("#firewallBody").html(body); $("#firewallPage").html(data.page); },'json'); diff --git a/web/utils/firewall.py b/web/utils/firewall.py index b69881868..84eea6e4e 100644 --- a/web/utils/firewall.py +++ b/web/utils/firewall.py @@ -8,3 +8,113 @@ # Author: midoks # --------------------------------------------------------------------------------- +import os +import re +import threading + +import core.mw as mw + +class Firewall(object): + + __isFirewalld = False + __isIptables = False + __isUfw = False + __isMac = False + + # lock + _instance_lock = threading.Lock() + + @classmethod + def instance(cls, *args, **kwargs): + if not hasattr(Firewall, "_instance"): + with Firewall._instance_lock: + if not hasattr(Firewall, "_instance"): + Firewall._instance = Firewall(*args, **kwargs) + return Firewall._instance + + def __init__(self): + iptables_file = mw.systemdCfgDir() + '/iptables.service' + if os.path.exists('/usr/sbin/firewalld'): + self.__isFirewalld = True + elif os.path.exists('/usr/sbin/ufw'): + self.__isUfw = True + elif os.path.exists(iptables_file): + self.__isIptables = True + elif mw.isAppleSystem(): + self.__isMac = True + + def getFwStatus(self): + if self.__isUfw: + cmd = "/usr/sbin/ufw status| grep Status | awk -F ':' '{print $2}'" + data = mw.execShell(cmd) + if data[0].strip() == 'inactive': + return False + return True + elif self.__isIptables: + cmd = "systemctl status iptables | grep 'inactive'" + data = mw.execShell(cmd) + if data[0] != '': + return False + return True + elif self.__isFirewalld: + cmd = "ps -ef|grep firewalld |grep -v grep | awk '{print $2}'" + data = mw.execShell(cmd) + if data[0] == '': + return False + return True + else: + return False + + + def getSshInfo(self): + data = {} + + file = '/etc/ssh/sshd_config' + conf = mw.readFile(file) + rep = r"#*Port\s+([0-9]+)\s*\n" + port = re.search(rep, conf).groups(0)[0] + + isPing = True + try: + if mw.isAppleSystem(): + isPing = True + else: + file = '/etc/sysctl.conf' + sys_conf = mw.readFile(file) + rep = r"#*net\.ipv4\.icmp_echo_ignore_all\s*=\s*([0-9]+)" + tmp = re.search(rep, sys_conf).groups(0)[0] + if tmp == '1': + isPing = False + except: + isPing = True + + # sshd 检测 + status = True + cmd = "service sshd status | grep -P '(dead|stop)'|grep -v grep" + ssh_status = mw.execShell(cmd) + if ssh_status[0] != '': + status = False + + cmd = "systemctl status sshd.service | grep 'dead'|grep -v grep" + ssh_status = mw.execShell(cmd) + if ssh_status[0] != '': + status = False + + data['pass_prohibit_status'] = False + # 密码登陆配置检查 + pass_rep = r"PasswordAuthentication\s+(\w*)\s*\n" + pass_status = re.search(pass_rep, conf) + if pass_status: + if pass_status and pass_status.groups(0)[0].strip() == 'no': + data['pass_prohibit_status'] = True + else: + data['pass_prohibit_status'] = True + + data['port'] = port + data['status'] = status + data['ping'] = isPing + if mw.isAppleSystem(): + data['firewall_status'] = False + else: + data['firewall_status'] = self.getFwStatus() + return mw.getJson(data) \ No newline at end of file diff --git a/web/utils/mwplugin.py b/web/utils/mwplugin.py index 4904672ac..cc81d9f37 100644 --- a/web/utils/mwplugin.py +++ b/web/utils/mwplugin.py @@ -10,7 +10,6 @@ import os import sys -import threading import json import threading import multiprocessing