diff --git a/.gitignore b/.gitignore index c47314ad2e..806ca813f5 100644 --- a/.gitignore +++ b/.gitignore @@ -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_* diff --git a/README.md b/README.md index 2337f28e7f..47ba88475a 100644 --- a/README.md +++ b/README.md @@ -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安装地址 diff --git a/class/core/config_api.py b/class/core/config_api.py index 71dd0d8966..bfd27b69c4 100755 --- a/class/core/config_api.py +++ b/class/core/config_api.py @@ -28,7 +28,7 @@ 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 @@ def getPanelSslApi(self): 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 @@ def getPanelSslData(self): 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 @@ def savePanelSslApi(self): 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 + '

响应状态:' + str(emsg['status']) + '

错误类型:' + emsg[ - 'type'] + '

错误代码:' + emsg['detail'] + '

' - 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 + '

响应状态:' + str(emsg['status']) + '

错误类型:' + emsg[ + # 'type'] + '

错误代码:' + emsg['detail'] + '

' + # 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, '证书错误:
' + isError.replace("\n", '
') + '
') - 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, '证书错误:
' + isError.replace("\n", '
') + '
') + # 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 @@ def getAuthSecretApi(self): 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 diff --git a/class/core/mw.py b/class/core/mw.py index e88a3f57e4..04d8d61866 100755 --- a/class/core/mw.py +++ b/class/core/mw.py @@ -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 diff --git a/cli.sh b/cli.sh index 14204b1d87..a06e185503 100755 --- a/cli.sh +++ b/cli.sh @@ -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 \ No newline at end of file diff --git a/plugins/sphinx/js/sphinx.js b/plugins/sphinx/js/sphinx.js index 44e231f183..ac3ae62f60 100755 --- a/plugins/sphinx/js/sphinx.js +++ b/plugins/sphinx/js/sphinx.js @@ -111,6 +111,7 @@ function autoMakeConf(){ \ \ \ ", @@ -286,7 +287,6 @@ function readme(){ con += '
  • 如果数据量比较大,第一次启动会失败!(可通过手动建立索引)
  • '; con += '
  • 以下内容,需手动加入计划任务。
  • '; - con += '
  • 全量:' + rdata['data']['cmd'] + ' --all --rotate
  • '; @@ -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 += '
  • 主索引 :' + rdata['data']['cmd'] + ' '+ index +' --rotate
  • '; - con += '
  • 增量索引 :' + rdata['data']['cmd'] + ' '+ delta +' --rotate
  • '; - con += '
  • 合并索引 :' + rdata['data']['cmd'] + ' --merge '+ index + ' ' + delta +' --rotate
  • '; + if (typeof(index_kv['delta']) != 'undefined'){ + var delta = index_kv['delta']; + con += '
  • 增量索引 :' + rdata['data']['cmd'] + ' '+ delta +' --rotate
  • '; + con += '
  • 合并索引 :' + rdata['data']['cmd'] + ' --merge '+ index + ' ' + delta +' --rotate
  • '; + } } con += ''; diff --git a/plugins/webstats/lua/webstats_common.lua b/plugins/webstats/lua/webstats_common.lua index e6670acb72..bd87bea910 100644 --- a/plugins/webstats/lua/webstats_common.lua +++ b/plugins/webstats/lua/webstats_common.lua @@ -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 diff --git a/route/__init__.py b/route/__init__.py index 0d12bded51..cd9855dff7 100755 --- a/route/__init__.py +++ b/route/__init__.py @@ -60,8 +60,7 @@ 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'}) diff --git a/route/static/app/config.js b/route/static/app/config.js index bba572d130..31f8b20776 100755 --- a/route/static/app/config.js +++ b/route/static/app/config.js @@ -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){ + // + layer.open({ + type:1, + closeBtn: 1, + title:"开启SSL证书", + area: ['600px','440px'], + btn: ["开启SSL证书访问"], + maxmin:false, + shadeClose: true, + content: '
    \ +
    \ +

    【开启SSL证书】保护面板访问安全

    \ +
    \ + \ +
    \ +
    \ + 类型\ +
    \ + \ +
    \ +
    \ + \ +
    \ +
    ', + 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: '
    \ +
    \ +
    关闭SSL极易被抓包攻击导致账号密码泄露,请勿关闭
    \ +
    \ +
    \ +
    请手动输入【我要关闭】,完成验证
    \ + \ +
    \ +
    ', + 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 = ''; + + //
    \ + // 强制HTTPS:\ + // \ + // \ + // \ + // \ + //
    \ if (cert['info']){ cert_data = "
    \
    证书品牌:\ @@ -726,16 +838,11 @@ function getPanelSSL(){
    \
    认证域名:\ "+cert['info']['subject']+"
    \ -
    \ - 强制HTTPS:\ - \ - \ - \ - \ -
    \
    "; } + // \ + // \ var certBody = '
    \
    \ '+cert_data+'\ @@ -750,7 +857,9 @@ function getPanelSSL(){
    \ \ \ - \ + \
    \
    \
      \ @@ -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'); diff --git a/route/static/app/files.js b/route/static/app/files.js index 2efbaa1e70..542bb38046 100755 --- a/route/static/app/files.js +++ b/route/static/app/files.js @@ -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); } diff --git a/route/static/img/phpmyadmin.png b/route/static/img/phpmyadmin.png deleted file mode 100755 index 56fbf2c9b8..0000000000 Binary files a/route/static/img/phpmyadmin.png and /dev/null differ diff --git a/route/static/img/pure-ftpd.png b/route/static/img/pure-ftpd.png deleted file mode 100755 index 8ac61bb453..0000000000 Binary files a/route/static/img/pure-ftpd.png and /dev/null differ diff --git a/route/static/img/pureftpd.png b/route/static/img/pureftpd.png deleted file mode 100755 index 8ac61bb453..0000000000 Binary files a/route/static/img/pureftpd.png and /dev/null differ diff --git a/route/static/img/soft_ico/ico-apache.png b/route/static/img/soft_ico/ico-apache.png deleted file mode 100755 index 3772caf0a4..0000000000 Binary files a/route/static/img/soft_ico/ico-apache.png and /dev/null differ diff --git a/route/static/img/soft_ico/ico-pure-ftpd.png b/route/static/img/soft_ico/ico-pure-ftpd.png deleted file mode 100755 index 8ec5eb803b..0000000000 Binary files a/route/static/img/soft_ico/ico-pure-ftpd.png and /dev/null differ diff --git a/route/static/img/soft_ico/ico-pureftpd.png b/route/static/img/soft_ico/ico-pureftpd.png deleted file mode 100755 index 93a29253b0..0000000000 Binary files a/route/static/img/soft_ico/ico-pureftpd.png and /dev/null differ diff --git a/route/static/img/soft_ico/ico-yunsuo.png b/route/static/img/soft_ico/ico-yunsuo.png deleted file mode 100755 index fdd86754a1..0000000000 Binary files a/route/static/img/soft_ico/ico-yunsuo.png and /dev/null differ diff --git a/route/templates/default/config.html b/route/templates/default/config.html index 900251c677..655630e3c0 100755 --- a/route/templates/default/config.html +++ b/route/templates/default/config.html @@ -54,7 +54,7 @@

      面板端口 - + 建议端口范围7200 - 65535

      diff --git a/scripts/init.d/mw.tpl b/scripts/init.d/mw.tpl index 79a3f1f4c9..21481f3284 100755 --- a/scripts/init.d/mw.tpl +++ b/scripts/init.d/mw.tpl @@ -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|" diff --git a/setting.py b/setting.py index cf91aeb78d..eac374df08 100755 --- a/setting.py +++ b/setting.py @@ -59,11 +59,17 @@ 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'): diff --git a/task.py b/task.py index 6ee7d24bc9..42546897af 100755 --- a/task.py +++ b/task.py @@ -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 @@ def setDaemon(t): 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) diff --git a/tools.py b/tools.py index b268bd6a22..6a050f9d99 100755 --- a/tools.py +++ b/tools.py @@ -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)