Merge pull request #583 from midoks/dev

0.17.0
pull/588/head 0.17.0
Mr Chen 1 year ago committed by GitHub
commit f6d4609947
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 25
      .gitignore
  2. 7
      README.md
  3. 584
      class/core/config_api.py
  4. 78
      class/core/mw.py
  5. 9
      cli.sh
  6. 12
      plugins/sphinx/js/sphinx.js
  7. 2
      plugins/webstats/lua/webstats_common.lua
  8. 6
      route/__init__.py
  9. 280
      route/static/app/config.js
  10. 2
      route/static/app/files.js
  11. BIN
      route/static/img/phpmyadmin.png
  12. BIN
      route/static/img/pure-ftpd.png
  13. BIN
      route/static/img/pureftpd.png
  14. BIN
      route/static/img/soft_ico/ico-apache.png
  15. BIN
      route/static/img/soft_ico/ico-pure-ftpd.png
  16. BIN
      route/static/img/soft_ico/ico-pureftpd.png
  17. BIN
      route/static/img/soft_ico/ico-yunsuo.png
  18. 2
      route/templates/default/config.html
  19. 31
      scripts/init.d/mw.tpl
  20. 16
      setting.py
  21. 50
      task.py
  22. 29
      tools.py

25
.gitignore vendored

@ -87,6 +87,7 @@ venv/
ENV/
env.bak/
venv.bak/
lib/python*
# Spyder project settings
.spyderproject
@ -98,6 +99,12 @@ venv.bak/
# mkdocs documentation
/site
bin
pyvenv.cfg
include
share
pip-selfcheck.json
# mypy
.mypy_cache/
@ -122,27 +129,17 @@ data/default.pl
data/backup.pl
data/debug.pl
data/default_site.pl
ssl/input.pl
lib/python*
bin
pyvenv.cfg
include
share
pip-selfcheck.json
data/ssl.pl
scripts/init.d/mw
scripts/mdserver-web
data/api_login.txt
data/sessions
data/ssl.pl
data/port.pl
data/ipv6.pl
data/restart.pl
data/ssl.pl
data/edate.pl
data/osname.pl
data/only_netio_counters.pl
@ -156,6 +153,10 @@ data/bind_domain.pl
data/unauthorized_status.pl
data/auth_secret.pl
ssl/local
ssl/nginx
ssl/choose.pl
plugins/vip_*
plugins/own_*
plugins/my_*

@ -110,12 +110,9 @@ docker run -itd --name mw-server --privileged=true -p 7200:7200 -p 80:80 -p 443:
```
### 版本更新 0.16.9
### 版本更新 0.17.0
- mysql同步优化,享受丝滑般感觉。
- 网站统计 - 实时-可调节1-10s。
- 网站统计 - 加入大小条件。
- Sphinx优化。
- 面板SSL调整。
### JSDelivr安装地址

@ -28,7 +28,7 @@ from flask import request
class config_api:
__version = '0.16.9'
__version = '0.17.0'
__api_addr = 'data/api.json'
# 统一默认配置文件
@ -42,7 +42,7 @@ class config_api:
'bind_domain' : 'data/bind_domain.pl', # 面板域名绑定
'unauth_status' : 'data/unauthorized_status.pl', # URL路径未成功显示状态
'auth_secret': 'data/auth_secret.pl', # 二次验证密钥
'ssl':'data/ssl.pl', # ssl设置
'ssl':'ssl/choose.pl', # ssl设置
'hook_database' : 'data/hook_database.json', # 数据库钩子
'hook_menu' : 'data/hook_menu.json', # 菜单钩子
'hook_global_static' : 'data/hook_global_static.json', # 静态文件钩子
@ -362,19 +362,23 @@ class config_api:
return mw.getJson(cert)
def getPanelSslData(self):
cert = {}
keyPath = 'ssl/private.pem'
certPath = 'ssl/cert.pem'
rdata = {}
choose_file = self.__file['ssl']
rdata['choose'] = mw.readFile(choose_file)
keyPath = 'ssl/local/private.pem'
certPath = 'ssl/local/cert.pem'
if not os.path.exists(certPath):
# 不再自动生成证书
# mw.createSSL()
cert['privateKey'] = ''
cert['is_https'] = ''
cert['certPem'] = ''
cert['rep'] = os.path.exists('ssl/input.pl')
cert['info'] = {'endtime': 0, 'subject': '',
'notAfter': '', 'notBefore': '', 'issuer': ''}
return cert
mw.createLocalSSL()
cert = {}
cert['privateKey'] = mw.readFile(keyPath)
cert['is_https'] = ''
cert['certPem'] = mw.readFile(certPath)
cert['info'] = mw.getCertName(certPath)
rdata['local'] = cert
panel_ssl = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
if not os.path.exists(panel_ssl):
@ -384,21 +388,68 @@ class config_api:
if ssl_data.find('$server_port !~ 443') != -1:
cert['is_https'] = 'checked'
keyPath = 'ssl/nginx/private.pem'
certPath = 'ssl/nginx/cert.pem'
cert = {}
cert['privateKey'] = mw.readFile(keyPath)
cert['certPem'] = mw.readFile(certPath)
cert['rep'] = os.path.exists('ssl/input.pl')
cert['info'] = mw.getCertName(certPath)
return cert
rdata['nginx'] = cert
return rdata
# 面板本地SSL设置
def setPanelLocalSslApi(self):
cert = {}
keyPath = 'ssl/local/private.pem'
certPath = 'ssl/local/cert.pem'
if not os.path.exists(certPath):
mw.createLocalSSL()
choose_file = self.__file['ssl']
mw.writeFile(choose_file, 'local')
mw.restartMw()
return mw.returnJson(True, '设置成功')
# 关闭SSL
def closePanelSslApi(self):
choose_file = self.__file['ssl']
if os.path.exists(choose_file):
os.remove(choose_file)
local_ssl = 'ssl/local'
if os.path.exists(local_ssl):
mw.execShell('rm -rf '+ local_ssl)
nginx_ssl = 'ssl/nginx'
if os.path.exists(nginx_ssl):
mw.execShell('rm -rf '+ nginx_ssl)
mw.restartMw()
return mw.returnJson(True, '关闭SSL成功')
# 保存面板证书
def savePanelSslApi(self):
keyPath = 'ssl/private.pem'
certPath = 'ssl/cert.pem'
checkCert = '/tmp/cert.pl'
choose = request.form.get('choose', '').strip()
certPem = request.form.get('certPem', '').strip()
privateKey = request.form.get('privateKey', '').strip()
if not mw.inArray(['local','nginx'], choose):
return mw.returnJson(True, '保存错误面板SSL类型!')
keyPath = 'ssl/'+choose+'/private.pem'
certPath = 'ssl/'+choose+'/cert.pem'
checkCert = '/tmp/cert.pl'
if not os.path.exists(keyPath):
return mw.returnJson(False, ''+choose+'】SSL类型不存在,先申请!')
if(privateKey.find('KEY') == -1):
return mw.returnJson(False, '秘钥错误,请检查!')
if(certPem.find('CERTIFICATE') == -1):
@ -411,258 +462,303 @@ class config_api:
mw.writeFile(certPath, certPem)
if not mw.checkCert(checkCert):
return mw.returnJson(False, '证书错误,请检查!')
mw.writeFile('ssl/input.pl', 'True')
return mw.returnJson(True, '证书已保存!')
# 设置面板SSL证书设置
def setPanelHttpToHttpsApi(self):
bind_domain = self.__file['bind_domain']
if not os.path.exists(bind_domain):
return mw.returnJson(False, '先要绑定域名!')
keyPath = 'ssl/private.pem'
if not os.path.exists(keyPath):
return mw.returnJson(False, '未申请SSL证书!')
is_https = request.form.get('https', '').strip()
panel_ssl = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
if not os.path.exists(panel_ssl):
return mw.returnJson(False, '未开启面板SSL!')
if is_https == 'false':
conf = mw.readFile(panel_ssl)
if conf:
if conf.find('ssl_certificate') == -1:
return mw.returnJson(False, '当前未开启SSL')
to = "#error_page 404/404.html;\n\
#HTTP_TO_HTTPS_START\n\
if ($server_port !~ 443){\n\
rewrite ^(/.*)$ https://$host$1 permanent;\n\
}\n\
#HTTP_TO_HTTPS_END"
conf = conf.replace('#error_page 404/404.html;', to)
mw.writeFile(panel_ssl, conf)
else:
conf = mw.readFile(panel_ssl)
if conf:
rep = "\n\\s*#HTTP_TO_HTTPS_START(.|\n){1,300}#HTTP_TO_HTTPS_END"
conf = re.sub(rep, '', conf)
rep = "\\s+if.+server_port.+\n.+\n\\s+\\s*}"
conf = re.sub(rep, '', conf)
mw.writeFile(panel_ssl, conf)
mw.restartWeb()
action = '开启'
if is_https == 'true':
action = '关闭'
return mw.returnJson(True, action + 'HTTPS跳转成功!')
# def setPanelHttpToHttpsApi(self):
# bind_domain = self.__file['bind_domain']
# if not os.path.exists(bind_domain):
# return mw.returnJson(False, '先要绑定域名!')
# choose_file = self.__file['ssl']
# choose = mw.readFile(choose_file)
# if choose == 'local':
# return mw.returnJson(False, '本地SSL无法使用!')
# keyPath = 'ssl/nginx/private.pem'
# if not os.path.exists(keyPath):
# return mw.returnJson(False, '未申请SSL证书!')
# is_https = request.form.get('https', '').strip()
# panel_ssl = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
# if not os.path.exists(panel_ssl):
# return mw.returnJson(False, '未开启面板SSL!')
# if is_https == 'false':
# conf = mw.readFile(panel_ssl)
# if conf:
# if conf.find('ssl_certificate') == -1:
# return mw.returnJson(False, '当前未开启SSL')
# to = "#error_page 404/404.html;\n\
# #HTTP_TO_HTTPS_START\n\
# if ($server_port !~ 443){\n\
# rewrite ^(/.*)$ https://$host$1 permanent;\n\
# }\n\
# #HTTP_TO_HTTPS_END"
# conf = conf.replace('#error_page 404/404.html;', to)
# mw.writeFile(panel_ssl, conf)
# else:
# conf = mw.readFile(panel_ssl)
# if conf:
# rep = "\n\\s*#HTTP_TO_HTTPS_START(.|\n){1,300}#HTTP_TO_HTTPS_END"
# conf = re.sub(rep, '', conf)
# rep = "\\s+if.+server_port.+\n.+\n\\s+\\s*}"
# conf = re.sub(rep, '', conf)
# mw.writeFile(panel_ssl, conf)
# mw.restartNginx()
# action = '开启'
# if is_https == 'true':
# action = '关闭'
# return mw.returnJson(True, action + 'HTTPS跳转成功!')
# 删除面板证书
def delPanelSslApi(self):
bind_domain = self.__file['bind_domain']
if not os.path.exists(bind_domain):
return mw.returnJson(False, '未绑定域名!')
ip = mw.getLocalIp()
if mw.isAppleSystem():
ip = '127.0.0.1'
siteName = mw.readFile(bind_domain).strip()
port = mw.readFile('data/port.pl').strip()
src_letpath = mw.getServerDir() + '/web_conf/letsencrypt/' + siteName
choose = request.form.get('choose', '').strip()
dst_letpath = mw.getRunDir() + '/ssl'
dst_csrpath = dst_letpath + '/cert.pem'
dst_keypath = dst_letpath + '/private.pem'
if not mw.inArray(['local','nginx'], choose):
return mw.returnJson(True, '删除错误面板SSL类型!')
if os.path.exists(src_letpath) or os.path.exists(dst_csrpath):
if os.path.exists(src_letpath):
mw.execShell('rm -rf ' + src_letpath)
if os.path.exists(dst_csrpath):
mw.execShell('rm -rf ' + dst_csrpath)
if os.path.exists(dst_keypath):
mw.execShell('rm -rf ' + dst_keypath)
# mw.restartWeb()
return mw.returnJson(True, '已经删除SSL!')
to_panel_url = 'http://'+ip+":"+port+'/config'
# mw.restartWeb()
return mw.returnJson(False, '已经不存在SSL!')
if choose == 'local':
dst_path = mw.getRunDir() + '/ssl/local'
ssl_file = self.__file['ssl']
if os.path.exists(dst_path):
mw.execShell('rm -rf ' + dst_path)
mw.execShell('rm -rf ' + ssl_file)
mw.restartMw();
return mw.returnJson(True, '删除本地面板SSL成功!',to_panel_url)
else:
return mw.returnJson(True, '已经删除本地面板SSL!',to_panel_url)
# 申请面板let证书
def applyPanelLetSslApi(self):
# check domain is bind?
bind_domain = self.__file['bind_domain']
if not os.path.exists(bind_domain):
return mw.returnJson(False, '先要绑定域名!')
siteName = mw.readFile(bind_domain).strip()
auth_to = mw.getRunDir() + "/tmp"
to_args = {
'domains': [siteName],
'auth_type': 'http',
'auth_to': auth_to,
}
if choose == 'nginx':
src_letpath = mw.getServerDir() + '/web_conf/letsencrypt/' + siteName
src_csrpath = src_letpath + "/fullchain.pem" # 生成证书路径
src_keypath = src_letpath + "/privkey.pem" # 密钥文件路径
dst_letpath = mw.getRunDir() + '/ssl'
dst_csrpath = dst_letpath + '/cert.pem'
dst_keypath = dst_letpath + '/private.pem'
is_already_apply = False
if not os.path.exists(src_letpath):
import cert_api
data = cert_api.cert_api().applyCertApi(to_args)
if not data['status']:
msg = data['msg']
if type(data['msg']) != str:
msg = data['msg'][0]
emsg = data['msg'][1]['challenges'][0]['error']
msg = msg + '<p><span>响应状态:</span>' + str(emsg['status']) + '</p><p><span>错误类型:</span>' + emsg[
'type'] + '</p><p><span>错误代码:</span>' + emsg['detail'] + '</p>'
return mw.returnJson(data['status'], msg, data['msg'])
else:
is_already_apply = True
bind_domain = self.__file['bind_domain']
if not os.path.exists(bind_domain):
return mw.returnJson(False, '未绑定域名!')
mw.buildSoftLink(src_csrpath, dst_csrpath, True)
mw.buildSoftLink(src_keypath, dst_keypath, True)
mw.execShell('echo "lets" > "' + dst_letpath + '/README"')
siteName = mw.readFile(bind_domain).strip()
data = self.getPanelSslData()
src_path = mw.getServerDir() + '/web_conf/letsencrypt/' + siteName
tmp_well_know = auth_to + '/.well-known'
if os.path.exists(tmp_well_know):
mw.execShell('rm -rf ' + tmp_well_know)
dst_path = mw.getRunDir() + '/ssl/nginx'
dst_csrpath = dst_path + '/cert.pem'
dst_keypath = dst_path + '/private.pem'
if is_already_apply:
return mw.returnJson(True, '重复申请!', data)
if os.path.exists(src_path) or os.path.exists(dst_path):
if os.path.exists(src_letpath):
mw.execShell('rm -rf ' + src_letpath)
if os.path.exists(dst_csrpath):
mw.execShell('rm -rf ' + dst_csrpath)
if os.path.exists(dst_keypath):
mw.execShell('rm -rf ' + dst_keypath)
mw.restartNginx()
return mw.returnJson(True, '删除面板SSL成功!')
return mw.returnJson(True, '申请成功!', data)
mw.restartNginx()
mw.restartMw()
return mw.returnJson(False, '已经删除面板SSL!')
return mw.returnJson(False, '未知类型!')
# 申请面板let证书
# def applyPanelAcmeSslApi(self):
# bind_domain = self.__file['bind_domain']
# if not os.path.exists(bind_domain):
# return mw.returnJson(False, '先要绑定域名!')
# # 生成nginx配置
# domain = mw.readFile(bind_domain)
# panel_tpl = mw.getRunDir() + "/data/tpl/nginx_panel.conf"
# dst_panel_path = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
# if not os.path.exists(dst_panel_path):
# reg = r"^([\w\-\*]{1,100}\.){1,4}(\w{1,10}|\w{1,10}\.\w{1,10})$"
# if not re.match(reg, domain):
# return mw.returnJson(False, '主域名格式不正确')
# op_dir = mw.getServerDir() + "/openresty"
# if not os.path.exists(op_dir):
# return mw.returnJson(False, '依赖OpenResty,先安装启动它!')
# content = mw.readFile(panel_tpl)
# content = content.replace("{$PORT}", "80")
# content = content.replace("{$SERVER_NAME}", domain)
# content = content.replace("{$PANAL_PORT}", mw.readFile('data/port.pl'))
# content = content.replace("{$LOGPATH}", mw.getRunDir() + '/logs')
# content = content.replace("{$PANAL_ADDR}", mw.getRunDir())
# mw.writeFile(dst_panel_path, content)
# mw.restartNginx()
# siteName = mw.readFile(bind_domain).strip()
# auth_to = mw.getRunDir() + "/tmp"
# to_args = {
# 'domains': [siteName],
# 'auth_type': 'http',
# 'auth_to': auth_to,
# }
# src_path = mw.getServerDir() + '/web_conf/letsencrypt/' + siteName
# src_csrpath = src_path + "/fullchain.pem" # 生成证书路径
# src_keypath = src_path + "/privkey.pem" # 密钥文件路径
# dst_path = mw.getRunDir() + '/ssl/nginx'
# dst_csrpath = dst_path + '/cert.pem'
# dst_keypath = dst_path + '/private.pem'
# is_already_apply = False
# if not os.path.exists(src_path):
# import cert_api
# data = cert_api.cert_api().applyCertApi(to_args)
# if not data['status']:
# msg = data['msg']
# if type(data['msg']) != str:
# msg = data['msg'][0]
# emsg = data['msg'][1]['challenges'][0]['error']
# msg = msg + '<p><span>响应状态:</span>' + str(emsg['status']) + '</p><p><span>错误类型:</span>' + emsg[
# 'type'] + '</p><p><span>错误代码:</span>' + emsg['detail'] + '</p>'
# return mw.returnJson(data['status'], msg, data['msg'])
# else:
# is_already_apply = True
# mw.buildSoftLink(src_csrpath, dst_csrpath, True)
# mw.buildSoftLink(src_keypath, dst_keypath, True)
# mw.execShell('echo "acme" > "' + dst_path + '/README"')
# tmp_well_know = auth_to + '/.well-known'
# if os.path.exists(tmp_well_know):
# mw.execShell('rm -rf ' + tmp_well_know)
# if os.path.exists(dst_path):
# choose_file = self.__file['ssl']
# mw.writeFile(choose_file, 'nginx')
# data = self.getPanelSslData()
# if is_already_apply:
# return mw.returnJson(True, '重复申请!', data)
# return mw.returnJson(True, '申请成功!', data)
def setPanelDomainApi(self):
domain = request.form.get('domain', '')
panel_tpl = mw.getRunDir() + "/data/tpl/nginx_panel.conf"
dst_panel_path = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
cfg_domain = self.__file['bind_domain']
port = mw.readFile('data/port.pl').strip()
ip = mw.getLocalIp()
if domain == '':
os.remove(cfg_domain)
os.remove(dst_panel_path)
mw.restartWeb()
return mw.returnJson(True, '清空域名成功!')
reg = r"^([\w\-\*]{1,100}\.){1,4}(\w{1,10}|\w{1,10}\.\w{1,10})$"
if not re.match(reg, domain):
return mw.returnJson(False, '主域名格式不正确')
op_dir = mw.getServerDir() + "/openresty"
if not os.path.exists(op_dir):
return mw.returnJson(False, '依赖OpenResty,先安装启动它!')
content = mw.readFile(panel_tpl)
content = content.replace("{$PORT}", "80")
content = content.replace("{$SERVER_NAME}", domain)
content = content.replace("{$PANAL_PORT}", mw.readFile('data/port.pl'))
content = content.replace("{$LOGPATH}", mw.getRunDir() + '/logs')
content = content.replace("{$PANAL_ADDR}", mw.getRunDir())
mw.writeFile(dst_panel_path, content)
mw.restartWeb()
if os.path.exists(cfg_domain):
os.remove(cfg_domain)
to_panel_url = 'http://'+ip+":"+port+'/config'
mw.restartMw()
return mw.returnJson(True, '清空域名成功!', to_panel_url)
mw.writeFile(cfg_domain, domain)
return mw.returnJson(True, '设置域名成功!')
to_panel_url = 'http://'+domain+":"+port+'/config'
mw.restartMw()
return mw.returnJson(True, '设置域名成功!',to_panel_url)
# 设置面板SSL
def setPanelSslApi(self):
sslConf = mw.getRunDir() + '/' + self.__file['ssl']
panel_tpl = mw.getRunDir() + "/data/tpl/nginx_panel.conf"
dst_panel_path = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
if os.path.exists(sslConf):
os.system('rm -f ' + sslConf)
conf = mw.readFile(dst_panel_path)
if conf:
rep = "\\s+ssl_certificate\\s+.+;\\s+ssl_certificate_key\\s+.+;"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl_protocols\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl_ciphers\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl_prefer_server_ciphers\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl_session_cache\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl_session_timeout\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl_ecdh_curve\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl_session_tickets\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl_stapling\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl_stapling_verify\\s+.+;\n"
conf = re.sub(rep, '', conf)
rep = "\\s+ssl\\s+on;"
conf = re.sub(rep, '', conf)
rep = "\\s+error_page\\s497.+;"
conf = re.sub(rep, '', conf)
rep = "\\s+if.+server_port.+\n.+\n\\s+\\s*}"
conf = re.sub(rep, '', conf)
rep = "\\s+listen\\s+443.*;"
conf = re.sub(rep, '', conf)
rep = "\\s+listen\\s+\\[\\:\\:\\]\\:443.*;"
conf = re.sub(rep, '', conf)
mw.writeFile(dst_panel_path, conf)
mw.writeLog('面板配置', '面板SSL关闭成功!')
mw.restartWeb()
return mw.returnJson(True, 'SSL已关闭,请使用http协议访问面板!')
else:
try:
mw.writeFile(sslConf, 'True')
keyPath = mw.getRunDir() + '/ssl/private.pem'
certPath = mw.getRunDir() + '/ssl/cert.pem'
conf = mw.readFile(dst_panel_path)
if conf:
if conf.find('ssl_certificate') == -1:
sslStr = """#error_page 404/404.html;
ssl_certificate %s;
ssl_certificate_key %s;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
ssl_prefer_server_ciphers on;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
error_page 497 https://$host$request_uri;""" % (certPath, keyPath)
if(conf.find('ssl_certificate') != -1):
return mw.returnJson(True, 'SSL开启成功!')
conf = conf.replace('#error_page 404/404.html;', sslStr)
rep = "listen\\s+([0-9]+)\\s*[default_server]*;"
tmp = re.findall(rep, conf)
if not mw.inArray(tmp, '443'):
listen = re.search(rep, conf).group()
http_ssl = "\n\tlisten 443 ssl http2;"
http_ssl = http_ssl + "\n\tlisten [::]:443 ssl http2;"
conf = conf.replace(listen, listen + http_ssl)
mw.backFile(dst_panel_path)
mw.writeFile(dst_panel_path, conf)
isError = mw.checkWebConfig()
if(isError != True):
mw.restoreFile(dst_panel_path)
return mw.returnJson(False, '证书错误: <br><a style="color:red;">' + isError.replace("\n", '<br>') + '</a>')
except Exception as ex:
return mw.returnJson(False, '开启失败:' + str(ex))
mw.restartWeb()
return mw.returnJson(True, '开启成功,请使用https协议访问面板!')
# def setPanelSslApi(self):
# sslConf = mw.getRunDir() + '/' + self.__file['ssl']
# panel_tpl = mw.getRunDir() + "/data/tpl/nginx_panel.conf"
# dst_panel_path = mw.getServerDir() + "/web_conf/nginx/vhost/panel.conf"
# if os.path.exists(sslConf):
# os.system('rm -f ' + sslConf)
# conf = mw.readFile(dst_panel_path)
# if conf:
# rep = "\\s+ssl_certificate\\s+.+;\\s+ssl_certificate_key\\s+.+;"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl_protocols\\s+.+;\n"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl_ciphers\\s+.+;\n"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl_prefer_server_ciphers\\s+.+;\n"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl_session_cache\\s+.+;\n"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl_session_timeout\\s+.+;\n"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl_ecdh_curve\\s+.+;\n"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl_session_tickets\\s+.+;\n"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl_stapling\\s+.+;\n"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl_stapling_verify\\s+.+;\n"
# conf = re.sub(rep, '', conf)
# rep = "\\s+ssl\\s+on;"
# conf = re.sub(rep, '', conf)
# rep = "\\s+error_page\\s497.+;"
# conf = re.sub(rep, '', conf)
# rep = "\\s+if.+server_port.+\n.+\n\\s+\\s*}"
# conf = re.sub(rep, '', conf)
# rep = "\\s+listen\\s+443.*;"
# conf = re.sub(rep, '', conf)
# rep = "\\s+listen\\s+\\[\\:\\:\\]\\:443.*;"
# conf = re.sub(rep, '', conf)
# mw.writeFile(dst_panel_path, conf)
# mw.writeLog('面板配置', '面板SSL关闭成功!')
# mw.restartWeb()
# return mw.returnJson(True, 'SSL已关闭,请使用http协议访问面板!')
# else:
# try:
# mw.writeFile(sslConf, 'True')
# keyPath = mw.getRunDir() + '/ssl/private.pem'
# certPath = mw.getRunDir() + '/ssl/cert.pem'
# conf = mw.readFile(dst_panel_path)
# if conf:
# if conf.find('ssl_certificate') == -1:
# sslStr = """#error_page 404/404.html;
# ssl_certificate %s;
# ssl_certificate_key %s;
# ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
# ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4:!DHE;
# ssl_prefer_server_ciphers on;
# ssl_session_cache shared:SSL:10m;
# ssl_session_timeout 10m;
# error_page 497 https://$host$request_uri;""" % (certPath, keyPath)
# if(conf.find('ssl_certificate') != -1):
# return mw.returnJson(True, 'SSL开启成功!')
# conf = conf.replace('#error_page 404/404.html;', sslStr)
# rep = "listen\\s+([0-9]+)\\s*[default_server]*;"
# tmp = re.findall(rep, conf)
# if not mw.inArray(tmp, '443'):
# listen = re.search(rep, conf).group()
# http_ssl = "\n\tlisten 443 ssl http2;"
# http_ssl = http_ssl + "\n\tlisten [::]:443 ssl http2;"
# conf = conf.replace(listen, listen + http_ssl)
# mw.backFile(dst_panel_path)
# mw.writeFile(dst_panel_path, conf)
# isError = mw.checkWebConfig()
# if(isError != True):
# mw.restoreFile(dst_panel_path)
# return mw.returnJson(False, '证书错误: <br><a style="color:red;">' + isError.replace("\n", '<br>') + '</a>')
# except Exception as ex:
# return mw.returnJson(False, '开启失败:' + str(ex))
# mw.restartWeb()
# return mw.returnJson(True, '开启成功,请使用https协议访问面板!')
def getApi(self):
data = {}
@ -958,7 +1054,7 @@ class config_api:
mw.writeFile(auth, crypt_data)
ip = mw.getHostAddr()
url = pyotp.totp.TOTP(sec).provisioning_uri(name=ip, issuer_name='mdserver-web')
url = pyotp.totp.TOTP(sec).provisioning_uri(name=ip, issuer_name=tag)
rdata = {}
rdata['secret'] = sec

@ -347,6 +347,9 @@ def restartMw():
import system_api
system_api.system_api().restartMw()
def restartNginx(self):
writeFile('data/restart_nginx.pl', 'True')
return True
def checkWebConfig():
op_dir = getServerDir() + '/openresty/nginx'
@ -1288,25 +1291,46 @@ def checkDomainPanel():
domain = readFile('data/bind_domain.pl')
port = readFile('data/port.pl').strip()
npid = getServerDir() + "/openresty/nginx/logs/nginx.pid"
if not os.path.exists(npid):
scheme = 'http'
choose_file = getRunDir()+'/ssl/choose.pl'
if os.path.exists(choose_file):
choose = readFile(choose_file).strip()
if not inArray(['local','nginx'], choose):
return False
else:
return False
nconf = getServerDir() + "/web_conf/nginx/vhost/panel.conf"
if os.path.exists(nconf):
port = "80"
local_ssl = getRunDir()+'/ssl/local'
if choose == 'local':
scheme = 'https'
if domain:
client_ip = getClientIp()
if client_ip in ['127.0.0.1', 'localhost', '::1']:
if choose == 'nginx':
# print(port)
npid = getServerDir() + "/openresty/nginx/logs/nginx.pid"
if not os.path.exists(npid):
return False
if tmp.strip().lower() != domain.strip().lower():
from flask import Flask, redirect, request, url_for
to = "http://" + domain + ":" + str(port)
return redirect(to, code=302)
nconf = getServerDir() + "/web_conf/nginx/vhost/panel.conf"
if os.path.exists(nconf):
port = "80"
if not domain:
return False
client_ip = getClientIp()
if client_ip in ['127.0.0.1', 'localhost', '::1']:
return False
if tmp.strip().lower() != domain.strip().lower():
from flask import Flask, redirect, request, url_for
to = scheme + "://" + domain + ":" + str(port)
# print(to)
return redirect(to, code=302)
return False
def createLinuxUser(user, group):
execShell("groupadd {}".format(group))
execShell('useradd -s /sbin/nologin -g {} {}'.format(user, group))
@ -1811,28 +1835,38 @@ def getCertName(certPath):
return None
def createSSL():
def createLocalSSL():
if not os.path.exists('ssl/local'):
execShell('mkdir -p ssl/local')
# 自签证书
if os.path.exists('ssl/input.pl'):
return True
# if os.path.exists('ssl/local/input.pl'):
# return True
client_ip = getClientIp()
import OpenSSL
key = OpenSSL.crypto.PKey()
key.generate_key(OpenSSL.crypto.TYPE_RSA, 2048)
cert = OpenSSL.crypto.X509()
cert.set_serial_number(0)
cert.get_subject().CN = getLocalIp()
if client_ip == '127.0.0.1':
cert.get_subject().CN = '127.0.0.1'
else:
cert.get_subject().CN = getLocalIp()
cert.set_issuer(cert.get_subject())
cert.gmtime_adj_notBefore(0)
cert.gmtime_adj_notAfter(86400 * 3650)
cert.set_pubkey(key)
cert.sign(key, 'md5')
cert_ca = OpenSSL.crypto.dump_certificate(
OpenSSL.crypto.FILETYPE_PEM, cert)
private_key = OpenSSL.crypto.dump_privatekey(
OpenSSL.crypto.FILETYPE_PEM, key)
cert_ca = OpenSSL.crypto.dump_certificate(OpenSSL.crypto.FILETYPE_PEM, cert)
private_key = OpenSSL.crypto.dump_privatekey(OpenSSL.crypto.FILETYPE_PEM, key)
if len(cert_ca) > 100 and len(private_key) > 100:
writeFile('ssl/cert.pem', cert_ca, 'wb+')
writeFile('ssl/private.pem', private_key, 'wb+')
writeFile('ssl/local/cert.pem', cert_ca, 'wb+')
writeFile('ssl/local/private.pem', private_key, 'wb+')
return True
return False

@ -64,6 +64,11 @@ mw_start_debug2(){
gunicorn -b :7200 -k geventwebsocket.gunicorn.workers.GeventWebSocketWorker -w 1 app:app
}
mw_start_debug3(){
gunicorn -c setting.py app:app
python3 task.py
}
mw_stop()
{
@ -96,4 +101,8 @@ case "$1" in
mw_stop
mw_start_debug2
;;
'debug3')
mw_stop
mw_start_debug3
;;
esac

@ -111,6 +111,7 @@ function autoMakeConf(){
</div>\
<ul class='help-info-text c7'>\
<li style='color:red;'>具体配置仍须手动修改!!!</li>'\
<li style='color:red;'>增量索引,需要有更新权限,主从分离时,需要主库配置</li>'\
</ul>\
</form>\
",
@ -286,7 +287,6 @@ function readme(){
con += '<li style="color:red;">如果数据量比较大,第一次启动会失败!(可通过手动建立索引)</li>';
con += '<li style="color:red;">以下内容,需手动加入计划任务。</li>';
con += '<li>全量:' + rdata['data']['cmd'] + ' --all --rotate</li>';
@ -294,11 +294,13 @@ function readme(){
for (var i = 0; i < rdata['data']['index'].length; i++) {
var index_kv = rdata['data']['index'][i];
var index = index_kv['index'];
var delta = index_kv['delta'];
// console.log(index,delta);
// console.log(index);
con += '<li>主索引 :' + rdata['data']['cmd'] + ' '+ index +' --rotate</li>';
con += '<li>增量索引 :' + rdata['data']['cmd'] + ' '+ delta +' --rotate</li>';
con += '<li>合并索引 :' + rdata['data']['cmd'] + ' --merge '+ index + ' ' + delta +' --rotate</li>';
if (typeof(index_kv['delta']) != 'undefined'){
var delta = index_kv['delta'];
con += '<li>增量索引 :' + rdata['data']['cmd'] + ' '+ delta +' --rotate</li>';
con += '<li>合并索引 :' + rdata['data']['cmd'] + ' --merge '+ index + ' ' + delta +' --rotate</li>';
}
}
con += '</ul>';

@ -636,7 +636,7 @@ function _M.statistics_request(self, ip, is_spider, body_length)
return pvc, uvc
end
-- 仅计算GET
-- 仅计算GET/HTML
function _M.statistics_request_old(self, ip, is_spider, body_length)
-- 计算pv uv
local pvc = 0

@ -60,8 +60,7 @@ try:
sdb.create_all()
except:
app.config['SESSION_TYPE'] = 'filesystem'
app.config['SESSION_FILE_DIR'] = '/tmp/py_mw_session_' + \
str(sys.version_info[0])
app.config['SESSION_FILE_DIR'] = '/tmp/py_mw_session_' + str(sys.version_info[0])
app.config['SESSION_FILE_THRESHOLD'] = 1024
app.config['SESSION_FILE_MODE'] = 384
@ -296,9 +295,6 @@ def code():
out = io.BytesIO()
codeImage[0].save(out, "png")
# print(codeImage[1])
session['code'] = mw.md5(''.join(codeImage[1]).lower())
img = Response(out.getvalue(), headers={'Content-Type': 'image/png'})

@ -75,16 +75,106 @@ $('input[name="bind_domain"]').change(function(){
$('.btn_bind_domain').removeAttr('disabled');
$('.btn_bind_domain').unbind().click(function(){
$.post('/config/set_panel_domain','domain='+domain, function(rdata){
showMsg(rdata.msg,function(){window.location.reload();},{icon:rdata.status?1:2},2000);
showMsg(rdata.msg,function(){
window.location.href = rdata.data;
},{icon:rdata.status?1:2},5000);
},'json');
});
});
$('input[name="bind_ssl"]').click(function(){
var open_ssl = $(this).prop("checked");
$.post('/config/set_panel_ssl',{}, function(rdata){
showMsg(rdata.msg,function(){window.location.reload();},{icon:rdata.status?1:2},2000);
},'json');
var panel_ssl = $(this).prop("checked");
$(this).prop("checked",!panel_ssl);
//开启证书
if (panel_ssl){
// <option value="1">ACME</option>
layer.open({
type:1,
closeBtn: 1,
title:"开启SSL证书",
area: ['600px','440px'],
btn: ["开启SSL证书访问"],
maxmin:false,
shadeClose: true,
content: '<div class="bt-form" style="padding: 25px 40px;">\
<div style="text-align: center;">\
<h3 style="font-size: 20px;color: #333;margin-left: 5px;">开启SSL证书保护面板访问安全</h3>\
</div>\
<ul class="help-info-text c7 pd15" style="color: #333;font-size: 14px;background: #F5F7FA;margin-top: 24px;padding: 10px 20px 10px 20px;border-radius: 2px;">\
<li>自签证书访问步骤</li>\
<li>1. 部署SSL证书</li>\
<li>2. 浏览器地址栏修改为https://访问</li>\
<li>3. 如提醒风险正常现象点击高级详情</li>\
<li>4.继续访问接收风险并继续</li>\
</ul>\
<div class="pt10" style="margin-top: 20px;">\
<div class="line" style="font-size: 14px;">\
<span class="tname" style="width: 78px;">类型</span>\
<div class="info-r" style="margin-left: 78px;">\
<select class="bt-input-text mr5" name="cert_type" style="width: 440px;">\
<option value="0">自签证书 (推荐浏览器会提示不安全可忽略请放心开启)</option>\
</select>\
</div>\
</div>\
<ul class="help-info-text c7 sslSafeTips">\
<li><span>开启后导致面板不能访问可以点击查看</span></li>\
<li>自签证书不被浏览器信任显示不安全是正常现象</li>\
</ul>\
</div>\
</div>',
yes: function(){
var cert_type = $('select[name=cert_type]').val();
$.post('/config/set_panel_local_ssl',{'cert_type':cert_type}, function(rdata){
// console.log(rdata);
var to_https = window.location.href.replace('http','https');
showMsg(rdata.msg,function(){
if (rdata.status){
window.location.href = to_https;
}
},{icon:rdata.status?1:2},5000);
},'json');
}
});
} else {
//关闭SSL
layer.open({
type:1,
closeBtn: 1,
title:"关闭SSL证书",
area: ['480px','280px'],
btn: ["确定","取消"],
shadeClose: true,
content: '<div class="bt-form" style="padding: 25px 40px;">\
<div class="hint_title" style="font-size: 15px;color: #111;text-align:center;">\
<div class="hint_con">关闭SSL极易被抓包攻击导致账号密码泄露请勿关闭</div>\
</div>\
<div class="confirm-info-box" style="background-color: #f0f0f0;clear: both;font-size: 14px;height: 105px;line-height: 26px;padding: 20px 20px;margin-top: 20px;">\
<div>请手动输入<span style="color: #fc6d26;">我要关闭</span></div>\
<input onpaste="return false;" id="prompt_input_box" style="height: 30px;line-height: 30px;margin-top: 5px;width: 360px;color: #444;outline: none;border: 1px solid #ccc;padding: 0 5px;" type="text" value="" autocomplete="off">\
</div>\
</div>',
yes: function(index){
var val = $('#prompt_input_box').val();
if (val != '我要关闭'){
layer.msg("关闭SSL失败!");
return;
}
$.post('/config/close_panel_ssl',{}, function(rdata){
var to_http = window.location.href.replace('https','http');
showMsg(rdata.msg,function(){
if (rdata.status){
window.location.href = to_http;
}
},{icon:rdata.status?1:2},5000);
},'json');
}
});
}
});
/** op **/
@ -714,8 +804,30 @@ function getPanelSSL(){
$.post('/config/get_panel_ssl',{},function(cert){
layer.close(loadT);
// console.log(cert);
var choose = cert['choose'];
var choose_local = '';
var choose_nginx = '';
if (choose == 'local'){
cert = cert['local'];
choose_local = 'selected="selected"';
} else if (choose == 'nginx') {
cert = cert['nginx'];
choose_nginx = 'selected="selected"';
} else {
cert = cert['local'];
}
var cert_data = '';
// <div class='state_item'>\
// <span>强制HTTPS:</span>\
// <span class='switch'>\
// <input class='btswitch btswitch-ios' id='toHttps' type='checkbox' "+cert['is_https']+">\
// <label class='btswitch-btn set_panel_http_to_https' for='toHttps'></label>\
// </span>\
// </div>\
if (cert['info']){
cert_data = "<div class='ssl_state_info'><div class='state_info_flex'>\
<div class='state_item'><span>证书品牌</span>\
@ -726,16 +838,11 @@ function getPanelSSL(){
<div class='state_info_flex'>\
<div class='state_item'><span>认证域名</span>\
<span class='ellipsis_text ssl_subject'>"+cert['info']['subject']+"</span></div>\
<div class='state_item'>\
<span>强制HTTPS</span>\
<span class='switch'>\
<input class='btswitch btswitch-ios' id='toHttps' type='checkbox' "+cert['is_https']+">\
<label class='btswitch-btn set_panel_http_to_https' for='toHttps'></label>\
</span>\
</div>\
</div></div>";
}
// <button class="btn btn-success btn-sm apply-lets-ssl">申请ACME证书</button>\
// <option value="nginx" '+choose_nginx+'>OpenResty</option>\
var certBody = '<div class="tab-con">\
<div class="myKeyCon ptb15">\
'+cert_data+'\
@ -750,7 +857,9 @@ function getPanelSSL(){
<div class="ssl-btn pull-left mtb15" style="width:100%">\
<button class="btn btn-success btn-sm save-panel-ssl">保存</button>\
<button class="btn btn-success btn-sm del-panel-ssl">删除</button>\
<button class="btn btn-success btn-sm apply-lets-ssl">申请Lets证书</button>\
<select class="bt-input-text" name="choose" style="width:100px;">\
<option value="local" '+choose_local+'>本地</option>\
</select>\
</div>\
</div>\
<ul class="help-info-text c7 pull-left">\
@ -768,65 +877,120 @@ function getPanelSSL(){
content:certBody,
success:function(layero, layer_id){
//保存SSL
$('.save-panel-ssl').click(function(){
var data = {
privateKey:$("#key").val(),
certPem:$("#csr").val()
}
var loadT = layer.msg('正在安装并设置SSL组件,这需要几分钟时间...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/config/save_panel_ssl',data,function(rdata){
layer.close(loadT);
if(rdata.status){
layer.closeAll();
}
layer.msg(rdata.msg,{icon:rdata.status?1:2});
},'json');
layer.confirm('选择保存面板SSL方式?',
{
title:'提示',
shade:0.001,
btn: ['本地SSL', '取消'],//'OpenResty'
btn3:function(){
data['choose'] = 'nginx';
var loadT = layer.msg('正在安装并设置SSL组件,这需要几分钟时间...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/config/save_panel_ssl',data,function(rdata){
layer.close(loadT);
if(rdata.status){
layer.closeAll();
}
layer.msg(rdata.msg,{icon:rdata.status?1:2});
},'json');
},
},
function(index) {
data['choose'] = 'local';
var loadT = layer.msg('正在安装并设置SSL组件,这需要几分钟时间...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/config/save_panel_ssl',data,function(rdata){
layer.close(loadT);
if(rdata.status){
layer.closeAll();
}
layer.msg(rdata.msg,{icon:rdata.status?1:2});
},'json');
},
function(index) {
layer.close(index);
});
});
//删除SSL
$('.del-panel-ssl').click(function(){
var loadT = layer.msg('正在删除SSL...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/config/del_panel_ssl',data,function(rdata){
layer.close(loadT);
if(rdata.status){
layer.closeAll();
}
layer.msg(rdata.msg,{icon:rdata.status?1:2});
},'json');
});
// 设置面板SSL的Http
$('.set_panel_http_to_https').click(function(){
var https = $('#toHttps').prop('checked');
$.post('/config/set_panel_http_to_https',{'https':https},function(rdata){
layer.close(loadT);
if(rdata.status){
layer.closeAll();
}
layer.msg(rdata.msg,{icon:rdata.status?1:2});
},'json');
});
//申请Lets证书
$('.apply-lets-ssl').click(function(){
showSpeedWindow('正在申请...', 'site.get_let_logs', function(layers,index){
$.post('/config/apply_panel_let_ssl',{},function(rdata){
layer.confirm('选择删除面板SSL方式?',
{
title:'提示',
shade:0.001,
btn: ['本地SSL', '取消'],//, 'OpenResty'
btn3:function(){
var data = {};
data['choose'] = 'nginx';
var loadT = layer.msg('正在删除面板SSL【nginx】...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/config/del_panel_ssl',data,function(rdata){
layer.close(loadT);
if(rdata.status){
layer.closeAll();
}
layer.msg(rdata.msg,{icon:rdata.status?1:2});
},'json');
},
},
function(index) {
var data = {};
data['choose'] = 'local';
var loadT = layer.msg('正在删除面板SSL【本地】...',{icon:16,time:0,shade: [0.3, '#000']});
$.post('/config/del_panel_ssl',data,function(rdata){
console.log(rdata);
layer.close(loadT);
if(rdata.status){
layer.close(index);
var tdata = rdata['data'];
$('.ssl_issue').text(tdata['info']['issuer']);
$('.ssl_endtime').text("剩余"+tdata['info']['endtime']+"天到期");
$('.ssl_subject').text(tdata['info']['subject']);
$('textarea[name="key"]').val(tdata['info']['privateKey']);
$('textarea[name="csr"]').val(tdata['info']['certPem']);
}
layer.msg(rdata.msg,{icon:rdata.status?1:2});
showMsg(rdata.msg, function(){
if(rdata.status){
location.href = rdata.data;
}
},{icon:rdata.status?1:2},3000);
},'json');
});
},
function(index) {
layer.close(index);
});
});
// // 设置面板SSL的Http
// $('.set_panel_http_to_https').click(function(){
// var https = $('#toHttps').prop('checked');
// $.post('/config/set_panel_http_to_https',{'https':https},function(rdata){
// layer.close(loadT);
// if(rdata.status){
// layer.closeAll();
// }
// layer.msg(rdata.msg,{icon:rdata.status?1:2});
// },'json');
// });
// //申请Lets证书
// $('.apply-lets-ssl').click(function(){
// showSpeedWindow('正在申请...', 'site.get_let_logs', function(layers,index){
// $.post('/config/apply_panel_acme_ssl',{},function(rdata){
// layer.close(loadT);
// if(rdata.status){
// layer.close(index);
// var tdata = rdata['data'];
// $('.ssl_issue').text(tdata['info']['issuer']);
// $('.ssl_endtime').text("剩余"+tdata['info']['endtime']+"天到期");
// $('.ssl_subject').text(tdata['info']['subject']);
// $('textarea[name="key"]').val(tdata['info']['privateKey']);
// $('textarea[name="csr"]').val(tdata['info']['certPem']);
// }
// layer.msg(rdata.msg,{icon:rdata.status?1:2});
// },'json');
// });
// });
}
});
},'json');

@ -294,7 +294,7 @@ function openFilename(obj){
onlineEditFile(0, path);
}
if (inArray(ext,['png','jpeg','gif','jpg','ico'])){
if (inArray(ext,['png','jpeg','jpg','gif','webp','bmp','ico'])){
getImage(path);
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 KiB

@ -54,7 +54,7 @@
<p class="mtb15">
<span class="set-tit text-right">面板端口</span>
<input data-port="{{data['port']}}" id="banport" name="port" class="inputtxt bt-input-text" type="numner" value="{{data['port']}}" maxlength="5">
<input data-port="{{data['port']}}" id="banport" name="port" class="inputtxt bt-input-text" type="number" value="{{data['port']}}" maxlength="5">
<button type="button" class="btn btn-success btn-sm ml5 btn_port" disabled>保存</button>
<span class="set-info c7">建议端口范围7200 - 65535</span>
</p>

@ -209,6 +209,21 @@ mw_unbind_domain()
fi
}
mw_unbind_ssl()
{
if [ -f $mw_path/local ];then
rm -rf $mw_path/local
fi
if [ -f $mw_path/nginx ];then
rm -rf $mw_path/nginx
fi
if [ -f $mw_path/ssl/choose.pl ];then
rm -rf $mw_path/ssl/choose.pl
fi
}
error_logs()
{
tail -n 100 $mw_path/logs/error.log
@ -445,6 +460,7 @@ case "$1" in
'install_app') mw_install_app;;
'close_admin_path') mw_close_admin_path;;
'unbind_domain') mw_unbind_domain;;
'unbind_ssl') mw_unbind_domain;;
'debug') mw_debug;;
'mirror') mw_mirror;;
'db') mw_connect_mysql;;
@ -454,6 +470,11 @@ case "$1" in
'default')
cd $mw_path
port=7200
scheme=http
if [ -f $mw_path/ssl/choose.pl ];then
scheme=https
fi
if [ -f $mw_path/data/port.pl ];then
port=$(cat $mw_path/data/port.pl)
@ -484,9 +505,9 @@ case "$1" in
mw_start
fi
address="MW-Panel-Url-Ipv4: http://$v4:$port$auth_path \nMW-Panel-Url-Ipv6: http://[$v6]:$port$auth_path"
address="MW-Panel-Url-Ipv4: ${scheme}://$v4:$port$auth_path \nMW-Panel-Url-Ipv6: ${scheme}://[$v6]:$port$auth_path"
elif [ "$v4" != "" ]; then
address="MW-Panel-Url: http://$v4:$port$auth_path"
address="MW-Panel-Url: ${scheme}://$v4:$port$auth_path"
elif [ "$v6" != "" ]; then
if [ ! -f $mw_path/data/ipv6.pl ];then
@ -495,12 +516,12 @@ case "$1" in
mw_stop
mw_start
fi
address="MW-Panel-Url: http://[$v6]:$port$auth_path"
address="MW-Panel-Url: ${scheme}://[$v6]:$port$auth_path"
else
address="MW-Panel-Url: http://you-network-ip:$port$auth_path"
address="MW-Panel-Url: ${scheme}://you-network-ip:$port$auth_path"
fi
else
address="MW-Panel-Url: http://$address:$port$auth_path"
address="MW-Panel-Url: ${scheme}://$address:$port$auth_path"
fi
show_panel_ip="$port|"

@ -59,11 +59,17 @@ if os.path.exists('data/ipv6.pl'):
else:
bind.append('0.0.0.0:%s' % mw_port)
# if os.path.exists('data/ssl.pl'):
# certfile = 'ssl/certificate.pem'
# keyfile = 'ssl/privateKey.pem'
# ciphers = 'TLSv1 TLSv1.1 TLSv1.2 TLSv1.3'
# ssl_version = 2
ssl_choose_file = 'ssl/choose.pl'
if os.path.exists(ssl_choose_file):
ssl_choose = mw.readFile(ssl_choose_file).strip()
if mw.inArray(['local','nginx'],ssl_choose):
tmp_cert = 'ssl/'+ssl_choose+'/cert.pem'
tmp_private = 'ssl/'+ssl_choose+'/private.pem'
if os.path.exists(tmp_cert) and os.path.exists(tmp_private):
certfile = tmp_cert
keyfile = tmp_private
ciphers = 'TLSv1 TLSv1.1 TLSv1.2 TLSv1.3'
ssl_version = 2
# 初始安装时,自动生成安全路径
if not os.path.exists('data/admin_path.pl'):

@ -64,6 +64,29 @@ def service_cmd(method):
return
def openresty_cmd(method = 'reload'):
# 检查是否安装
odir = mw.getServerDir() + '/openresty'
if not os.path.exists(odir):
return False
# systemd
systemd = mw.systemdCfgDir()+'/openresty.service'
if os.path.exists(systemd):
execShell('systemctl ' + method + ' openresty')
return True
sys_initd = '/etc/init.d/openresty'
if os.path.exists(install_initd):
os.system(sys_initd + ' ' + method)
return True
install_initd = mw.getServerDir()+'/openresty/init.d/openresty'
if os.path.exists(install_initd):
os.system(install_initd + ' ' + method)
return True
return False
def mw_async(f):
def wrapper(*args, **kwargs):
thr = threading.Thread(target=f, args=args, kwargs=kwargs)
@ -539,13 +562,7 @@ def openrestyAutoRestart():
time.sleep(86400)
continue
# systemd
systemd = mw.systemdCfgDir()+'/openresty.service'
initd = '/etc/init.d/openresty'
if os.path.exists(systemd):
execShell('systemctl reload openresty')
elif os.path.exists(initd):
os.system(initd + ' reload')
openresty_cmd('reload')
time.sleep(86400)
except Exception as e:
print(str(e))
@ -553,6 +570,18 @@ def openrestyAutoRestart():
# --------------------------------------OpenResty Auto Restart End --------------------------------------------- #
# ------------------------------------ OpenResty Restart At Once Start ------------------------------------------ #
def openrestyRestartAtOnce():
restart_nginx_tip = 'data/restart_nginx.pl'
while True:
if os.path.exists(restart_nginx_tip):
os.remove(restart_nginx_tip)
openresty_cmd('reload')
time.sleep(1)
# ----------------------------------- OpenResty Restart At Once End ------------------------------------------ #
# --------------------------------------Panel Restart Start --------------------------------------------- #
def restartPanelService():
@ -584,11 +613,18 @@ if __name__ == "__main__":
php502 = setDaemon(php502)
php502.start()
# OpenResty Restart At Once Start
oraos = threading.Thread(target=openrestyRestartAtOnce)
oraos = setDaemon(oraos)
oraos.start()
# OpenResty Auto Restart Start
oar = threading.Thread(target=openrestyAutoRestart)
oar = setDaemon(oar)
oar.start()
# Panel Restart Start
rps = threading.Thread(target=restartPanelService)
rps = setDaemon(rps)

@ -58,11 +58,12 @@ def mwcli(mw_input=0):
print("(13) 显示面板错误日志")
print("(20) 关闭BasicAuth认证")
print("(21) 解除域名绑定")
print("(22) 开启IPV6支持")
print("(23) 关闭IPV6支持")
print("(24) 开启防火墙SSH端口")
print("(25) 关闭二次验证")
print("(26) 查看防火墙信息")
print("(22) 解除面板SSL绑定")
print("(23) 开启IPV6支持")
print("(24) 关闭IPV6支持")
print("(25) 开启防火墙SSH端口")
print("(26) 关闭二次验证")
print("(27) 查看防火墙信息")
print("(100) 开启PHP52显示")
print("(101) 关闭PHP52显示")
print("(200) 切换Linux系统软件源")
@ -77,8 +78,8 @@ def mwcli(mw_input=0):
mw_input = 0
nums = [
1, 2, 3, 4, 5, 10, 11, 12, 13,
20, 21, 22, 23, 24, 25, 26,
1, 2, 3, 4, 5, 10, 11, 12, 13,
20, 21, 22, 23, 24, 25, 26, 27,
100, 101,
200, 201
]
@ -134,6 +135,12 @@ def mwcli(mw_input=0):
os.system(INIT_CMD + " unbind_domain")
print("|-解除域名绑定成功")
elif mw_input == 22:
ssl_choose = 'ssl/choose.pl'
if os.path.exists(ssl_choose):
os.remove(ssl_choose)
os.system(INIT_CMD + " unbind_ssl")
print("|-解除面板SSL绑定成功")
elif mw_input == 23:
listen_ipv6 = 'data/ipv6.pl'
if not os.path.exists(listen_ipv6):
mw.writeFile(listen_ipv6,'True')
@ -141,7 +148,7 @@ def mwcli(mw_input=0):
print("|-开启IPv6支持了")
else:
print("|-已开启IPv6支持!")
elif mw_input == 23:
elif mw_input == 24:
listen_ipv6 = 'data/ipv6.pl'
if not os.path.exists(listen_ipv6):
print("|-已关闭IPv6支持!")
@ -149,17 +156,17 @@ def mwcli(mw_input=0):
os.remove(listen_ipv6)
os.system(INIT_CMD + " restart")
print("|-关闭IPv6支持了")
elif mw_input == 24:
elif mw_input == 25:
open_ssh_port()
print("|-已开启!")
elif mw_input == 25:
elif mw_input == 26:
auth_secret = 'data/auth_secret.pl'
if os.path.exists(auth_secret):
os.remove(auth_secret)
print("|-关闭二次验证成功!")
else:
print("|-二次验证已关闭!")
elif mw_input == 26:
elif mw_input == 27:
cmd = 'which ufw'
run_cmd = False
find_cmd = mw.execShell(cmd)

Loading…
Cancel
Save