diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua index 755a2680d..f29fa7579 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_v2ray.lua @@ -147,7 +147,8 @@ function gen_outbound(node, tag, proxy_table) security = node.stream_security, xtlsSettings = (node.stream_security == "xtls") and { serverName = node.tls_serverName, - allowInsecure = (node.tls_allowInsecure == "1") and true or false + allowInsecure = (node.tls_allowInsecure == "1") and true or false, + fingerprint = (node.type == "Xray" and node.fingerprint and node.fingerprint ~= "disable") and node.fingerprint or nil } or nil, tlsSettings = (node.stream_security == "tls") and { serverName = node.tls_serverName, @@ -216,7 +217,7 @@ function gen_outbound(node, tag, proxy_table) level = 0, security = (node.protocol == "vmess") and node.security or nil, encryption = node.encryption or "none", - flow = node.flow or nil + flow = node.flow or (node.tls == '1' and node.xtls ~= '1' and node.tlsflow) and node.tlsflow or nil } } } @@ -226,7 +227,7 @@ function gen_outbound(node, tag, proxy_table) address = node.address, port = tonumber(node.port), method = node.method or nil, - flow = node.flow or nil, + flow = node.flow or (node.tls == '1' and node.xtls ~= '1' and node.tlsflow) and node.tlsflow or nil, ivCheck = (node.protocol == "shadowsocks") and node.iv_check == "1" or nil, uot = (node.protocol == "shadowsocks") and node.uot == "1" or nil, password = node.password or "", diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua index 1fad55212..6c7de4695 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua @@ -511,6 +511,13 @@ xtls.default = 0 xtls:depends({ type = "Xray", protocol = "vless", tls = true }) xtls:depends({ type = "Xray", protocol = "trojan", tls = true }) +tlsflow = s:option(Value, "tlsflow", translate("flow")) +tlsflow.default = "" +tlsflow:value("", translate("Disable")) +tlsflow:value("xtls-rprx-vision") +tlsflow:value("xtls-rprx-vision-udp443") +tlsflow:depends({ type = "Xray", protocol = "vless", tls = true , xtls = false }) + flow = s:option(Value, "flow", translate("flow")) flow.default = "xtls-rprx-direct" flow:value("xtls-rprx-origin") @@ -530,6 +537,11 @@ alpn:value("http/1.1") alpn:depends({ type = "V2ray", tls = true }) alpn:depends({ type = "Xray", tls = true }) +-- minversion = s:option(Value, "minversion", translate("minversion")) +-- minversion.default = "1.3" +-- minversion:value("1.3") +-- minversion:depends("tls", true) + -- [[ TLS部分 ]] -- tls_sessionTicket = s:option(Flag, "tls_sessionTicket", translate("Session Ticket")) tls_sessionTicket.default = "0" @@ -568,6 +580,7 @@ xray_fingerprint:value("safari") xray_fingerprint:value("randomized") xray_fingerprint.default = "disable" xray_fingerprint:depends({ type = "Xray", tls = true, xtls = false }) +xray_fingerprint:depends({ type = "Xray", tls = true, xtls = true }) function xray_fingerprint.cfgvalue(self, section) return m:get(section, "fingerprint") end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua index 729d9f204..273487eb7 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/api/v2ray.lua @@ -14,7 +14,7 @@ function gen_config(user) for i = 1, #user.uuid do clients[i] = { id = user.uuid[i], - flow = ("1" == user.xtls) and user.flow or nil + flow = ("1" == user.xtls) and user.flow or ("1" == user.tls and "1" ~= user.xtls and user.tlsflow) and user.tlsflow or nil } end settings = { @@ -57,7 +57,7 @@ function gen_config(user) local clients = {} for i = 1, #user.uuid do clients[i] = { - flow = ("1" == user.xtls) and user.flow or nil, + flow = ("1" == user.xtls) and user.flow or ("1" == user.tls and "1" ~= user.xtls and user.tlsflow) and user.tlsflow or nil, password = user.uuid[i], } end diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua index 13cc72b4e..c438ed115 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua @@ -392,6 +392,13 @@ xtls.default = 0 xtls:depends({ type = "Xray", protocol = "vless", tls = true }) xtls:depends({ type = "Xray", protocol = "trojan", tls = true }) +tlsflow = s:option(Value, "tlsflow", translate("flow")) +tlsflow.default = "" +tlsflow:value("", translate("Disable")) +tlsflow:value("xtls-rprx-vision") +tlsflow:value("xtls-rprx-vision-udp443") +tlsflow:depends({ type = "Xray", protocol = "vless", tls = true , xtls = false }) + flow = s:option(Value, "flow", translate("flow")) flow.default = "xtls-rprx-direct" flow:value("xtls-rprx-origin") @@ -406,6 +413,11 @@ alpn:value("http/1.1") alpn:depends({ type = "V2ray", tls = true }) alpn:depends({ type = "Xray", tls = true }) +-- minversion = s:option(Value, "minversion", translate("minversion")) +-- minversion.default = "1.3" +-- minversion:value("1.3") +-- minversion:depends("tls", true) + -- [[ TLS部分 ]] -- tls_certificateFile = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") diff --git a/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm b/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm index 5bbd1a299..937ed61eb 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_list/link_share_man.htm @@ -285,19 +285,30 @@ local has_xray = api.is_finded("xray") params += "&type=" + v_transport; params += opt.query("encryption", "encryption"); + if (opt.get("tls").checked) { - var v_security = "tls"; - if (opt.get("xtls").checked) { - v_security = "xtls"; + var v_security = "tls"; + var v_flow = "xtls-rprx-vision"; + if (opt.get("tlsflow").value) { + v_flow = opt.get("tlsflow").value; + } + params += "&flow=" + v_flow; + params += "&security=" + v_security; + params += opt.query("sni", "tls_serverName"); + } + + if (opt.get("xtls").checked) { + var v_security = "xtls"; var v_flow = "xtls-rprx-direct"; if (opt.get("flow").value) { v_flow = opt.get("flow").value; } params += "&flow=" + v_flow; - } - params += "&security=" + v_security; - params += opt.query("sni", "tls_serverName"); + params += "&security=" + v_security; + params += opt.query("sni", "tls_serverName"); } + + params += "#" + encodeURI(v_alias.value); if (params[0] == "&") { params = params.substring(1); @@ -850,14 +861,22 @@ local has_xray = api.is_finded("xray") opt.set('encryption', queryParam.encryption); if (queryParam.security) { - if (queryParam.security == "tls" || queryParam.security == "xtls") { + if (queryParam.security == "tls") { opt.set('tls', true); - if (queryParam.security == "xtls") { - opt.set('xtls', true); - opt.set('flow', queryParam.flow || "xtls-rprx-direct"); - } + opt.set('xtls',false); + opt.set('tlsflow', queryParam.flow || ''); + opt.set('tls_serverName', queryParam.sni || ''); + opt.set('tls_allowInsecure', true); + if (queryParam.allowinsecure === '0') { + opt.set('tls_allowInsecure', false); + } + } + + if (queryParam.security == "xtls") { + opt.set('tls', true); + opt.set('xtls',true); + opt.set('flow', queryParam.flow || "xtls-rprx-direct"); opt.set('tls_serverName', queryParam.sni || ''); - opt.set('tls_allowInsecure', true); if (queryParam.allowinsecure === '0') { opt.set('tls_allowInsecure', false); diff --git a/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/luci-app-passwall/root/usr/share/passwall/subscribe.lua index d69429b80..29447fffe 100755 --- a/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -776,6 +776,8 @@ local function processData(szType, content, add_mode, add_from) if params.security == "xtls" then result.xtls = "1" result.flow = params.flow or "xtls-rprx-direct" + else + result.tlsflow = params.flow or nil end result.tls_serverName = (params.sni and params.sni ~= "") and params.sni or params.host end diff --git a/luci-app-quickstart/API.md b/luci-app-quickstart/API.md new file mode 100644 index 000000000..47c59efe7 --- /dev/null +++ b/luci-app-quickstart/API.md @@ -0,0 +1,24 @@ +## API +这里列出的接口都是 lua 实现的,对于 POST 请求都是提交表单( `multipart/form-data` 或者 `application/x-www-form-urlencoded` ),而不是 JSON,并且 POST 请求必须提供 `token` 参数用于防止 CSRF,`token` 的值可以从全局变量 `window.token` 取得。 + +1. 自动安装配置软件包 + ``` + POST /cgi-bin/luci/admin/nas/quickstart/auto_setup + token=xxx&packages=aria2&packages=qbittorrent + + + {"success":0} + {"success":1, "scope":"taskd", "error":"task already running"} + ``` + 这是个异步接口,除非任务已经在运行,否则都会成功(success=0)。`packages` 是需要安装配置的软件包列表,与元数据的id对应 + +2. 获取安装配置结果 + ``` + GET /cgi-bin/luci/admin/nas/quickstart/setup_result + + + {"success":0, "result": {"ongoing": true, "packages": ["aria2", "qbittorrent"], "success":["aria2"], "failed":[]} } + {"success":404, "scope":"taskd", "error":"task not found"} + ``` + 用于在安装过程中或者安装完成时获取当前状态。 + 安装过程中或者安装完成时,`success` 都是 0,`result.ongoing` 表示是否在安装过程中,`result.packages` 是提交的任务列表,`result.success` 是已成功的任务列表,`result.failed` 是已失败的任务列表 diff --git a/luci-app-quickstart/Makefile b/luci-app-quickstart/Makefile index 1b1bff2eb..93327a6be 100644 --- a/luci-app-quickstart/Makefile +++ b/luci-app-quickstart/Makefile @@ -9,7 +9,7 @@ LUCI_TITLE:=LuCI support for quickstart LUCI_DEPENDS:=+quickstart +luci-app-store LUCI_PKGARCH:=all -PKG_VERSION:=0.5.8-1 +PKG_VERSION:=0.5.9-1 # PKG_RELEASE MUST be empty for luci.mk PKG_RELEASE:= diff --git a/luci-app-quickstart/luasrc/controller/quickstart.lua b/luci-app-quickstart/luasrc/controller/quickstart.lua index bba88d47b..22fe7c549 100644 --- a/luci-app-quickstart/luasrc/controller/quickstart.lua +++ b/luci-app-quickstart/luasrc/controller/quickstart.lua @@ -13,6 +13,10 @@ function index() entry({"admin", "nas", "raid"}, call("quickstart_index", {index={"admin", "nas"}}), _("RAID"), 10).leaf = true entry({"admin", "nas", "smart"}, call("quickstart_index", {index={"admin", "nas"}}), _("S.M.A.R.T."), 11).leaf = true entry({"admin", "network", "interfaceconfig"}, call("quickstart_index", {index={"admin", "network"}}), _("NetworkPort"), 11).leaf = true + + entry({"admin", "nas", "quickstart"}).dependent = false + entry({"admin", "nas", "quickstart", "auto_setup"}, post("auto_setup")) + entry({"admin", "nas", "quickstart", "setup_result"}, call("setup_result")) else entry({"admin", "quickstart"}, call("redirect_fallback")).leaf = true end @@ -33,3 +37,116 @@ end function quickstart_dev(param) luci.template.render("quickstart/main_dev", {prefix=luci.dispatcher.build_url(unpack(param.index))}) end + +function auto_setup() + local os = require "os" + local fs = require "nixio.fs" + local rshift = nixio.bit.rshift + + -- json style + -- local jsonc = require "luci.jsonc" + -- local json_parse = jsonc.parse + -- local req = json_parse(luci.http.content()) + -- local pkgs = "" + -- for k, v in pairs(req.packages) do + -- pkgs = pkgs .. " " .. luci.util.shellquote(v) + -- end + + -- form style + local packages = luci.http.formvalue("packages") + local pkgs = "" + if type(packages) == "table" then + if #packages > 0 then + for k, v in pairs(packages) do + pkgs = pkgs .. " " .. luci.util.shellquote(v) + end + end + else + if packages ~= nil and packages ~= "" then + pkgs = luci.util.shellquote(packages) + end + end + + + local ret + if pkgs == "" then + ret = { + success = 1, + scope = "params", + error = "Parameter 'packages' undefined!", + } + else + local cmd = "/usr/libexec/quickstart/auto_setup.sh " .. pkgs + cmd = "/etc/init.d/tasks task_add auto_setup " .. luci.util.shellquote(cmd) + local r = os.execute(cmd .. " >/var/log/auto_setup.stdout 2>/var/log/auto_setup.stderr") + local e = fs.readfile("/var/log/auto_setup.stderr") + local o = fs.readfile("/var/log/auto_setup.stdout") + + fs.unlink("/var/log/auto_setup.stderr") + fs.unlink("/var/log/auto_setup.stdout") + e = e or "" + if r == 256 and e == "" then + e = "os.execute exit code 1" + end + r = rshift(r,8) + ret = { + success = r, + scope = "taskd", + error = e, + detail = o, + } + end + luci.http.prepare_content("application/json") + luci.http.write_json(ret) +end + +function setup_result() + local fs = require "nixio.fs" + local taskd = require "luci.model.tasks" + local packages = nil + local success = nil + local failed = nil + local status = taskd.status("auto_setup") + local ret = { + } + if status.running or status.exit_code ~= 404 then + local item + local po = fs.readfile("/var/log/auto_setup.input") or "" + for item in po:gmatch("[^\n]+") do + if packages then + packages[#packages+1] = item + else + packages = {item} + end + end + local so = fs.readfile("/var/log/auto_setup.success") or "" + for item in so:gmatch("[^\n]+") do + if success then + success[#success+1] = item + else + success = {item} + end + end + local fo = fs.readfile("/var/log/auto_setup.failed") or "" + for item in fo:gmatch("[^\n]+") do + if failed then + failed[#failed+1] = item + else + failed = {item} + end + end + ret.success = 0 + ret.result = { + ongoing = status.running, + packages = packages, + success = success, + failed = failed, + } + else + ret.success = 404 + ret.scope = "taskd" + ret.error = "task not found" + end + luci.http.prepare_content("application/json") + luci.http.write_json(ret) +end diff --git a/luci-app-quickstart/luasrc/view/quickstart/main.htm b/luci-app-quickstart/luasrc/view/quickstart/main.htm index 1d3852ee6..8e4ee7fb1 100644 --- a/luci-app-quickstart/luasrc/view/quickstart/main.htm +++ b/luci-app-quickstart/luasrc/view/quickstart/main.htm @@ -14,6 +14,7 @@ -%>