From f440413649922fbcc8508f90c77da5d9b83c4ffb Mon Sep 17 00:00:00 2001 From: sbwml Date: Wed, 20 Sep 2023 21:25:22 +0800 Subject: [PATCH] luci-app-passwall2: sync upstream --- .../model/cbi/passwall2/client/other.lua | 2 +- .../cbi/passwall2/client/type/sing-box.lua | 54 +++++++++++---- .../model/cbi/passwall2/server/type/ray.lua | 10 +-- .../cbi/passwall2/server/type/sing-box.lua | 10 +-- luci-app-passwall2/luasrc/passwall2/api.lua | 11 +++- .../luasrc/passwall2/util_sing-box.lua | 66 ++++++++++++++++++- 6 files changed, 129 insertions(+), 24 deletions(-) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua index f1f3788c8..853f615b7 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/other.lua @@ -147,7 +147,7 @@ if has_xray then o.cfgvalue = function(self, section) return fs.readfile(domains_excluded) or "" end o.write = function(self, section, value) fs.writefile(domains_excluded, value:gsub("\r\n", "\n")) end o.remove = function(self, section) - local route_only_value = s_xray.fields["route_only"]:formvalue(section) + local route_only_value = s_xray.fields["route_only"] and s_xray.fields["route_only"]:formvalue(section) or nil if not route_only_value or route_only_value == "0" then fs.writefile(domains_excluded, "") end diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua index 919558e07..53706cccc 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua @@ -50,7 +50,6 @@ end if singbox_tags:find("with_quic") then o:value("hysteria", "Hysteria") end -o:value("shadowtls", "ShadowTLS") o:value("vless", "VLESS") if singbox_tags:find("with_quic") then o:value("tuic", "TUIC") @@ -176,13 +175,6 @@ if #protocols > 0 then end end -o = s:option(ListValue, option_name("shadowtls_version"), translate("Version")) -o.default = "1" -o:value("1", "ShadowTLS v1") -o:value("2", "ShadowTLS v2") -o:value("3", "ShadowTLS v3") -o:depends({ [option_name("protocol")] = "shadowtls" }) - o = s:option(Value, option_name("username"), translate("Username")) o:depends({ [option_name("protocol")] = "http" }) o:depends({ [option_name("protocol")] = "socks" }) @@ -194,8 +186,6 @@ o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "shadowsocks" }) o:depends({ [option_name("protocol")] = "shadowsocksr" }) o:depends({ [option_name("protocol")] = "trojan" }) -o:depends({ [option_name("protocol")] = "shadowtls", [option_name("shadowtls_version")] = "2" }) -o:depends({ [option_name("protocol")] = "shadowtls", [option_name("shadowtls_version")] = "3" }) o:depends({ [option_name("protocol")] = "tuic" }) o = s:option(ListValue, option_name("security"), translate("Encrypt Method")) @@ -366,7 +356,6 @@ o:depends({ [option_name("protocol")] = "vless" }) o:depends({ [option_name("protocol")] = "socks" }) o:depends({ [option_name("protocol")] = "trojan" }) o:depends({ [option_name("protocol")] = "shadowsocks" }) -o:depends({ [option_name("protocol")] = "shadowtls" }) o = s:option(ListValue, option_name("alpn"), translate("alpn")) o.default = "default" @@ -542,4 +531,47 @@ o = s:option(Flag, option_name("mux_padding"), translate("Padding")) o.default = 0 o:depends({ [option_name("mux")] = true }) +o = s:option(Flag, option_name("shadowtls"), "ShadowTLS") +o.default = 0 +o:depends({ [option_name("protocol")] = "vmess" }) +o:depends({ [option_name("protocol")] = "vless" }) +o:depends({ [option_name("protocol")] = "socks" }) +o:depends({ [option_name("protocol")] = "trojan" }) +o:depends({ [option_name("protocol")] = "shadowsocks" }) + +o = s:option(ListValue, option_name("shadowtls_version"), "ShadowTLS " .. translate("Version")) +o.default = "1" +o:value("1", "ShadowTLS v1") +o:value("2", "ShadowTLS v2") +o:value("3", "ShadowTLS v3") +o:depends({ [option_name("shadowtls")] = true }) + +o = s:option(Value, option_name("shadowtls_password"), "ShadowTLS " .. translate("Password")) +o.password = true +o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_version")] = "2" }) +o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_version")] = "3" }) + +o = s:option(Value, option_name("shadowtls_serverName"), "ShadowTLS " .. translate("Domain")) +o:depends({ [option_name("shadowtls")] = true }) + +if singbox_tags:find("with_utls") then + o = s:option(Flag, option_name("shadowtls_utls"), "ShadowTLS " .. translate("uTLS")) + o.default = "0" + o:depends({ [option_name("shadowtls")] = true }) + + o = s:option(ListValue, option_name("shadowtls_fingerprint"), "ShadowTLS " .. translate("Finger Print")) + o:value("chrome") + o:value("firefox") + o:value("edge") + o:value("safari") + -- o:value("360") + o:value("qq") + o:value("ios") + -- o:value("android") + o:value("random") + -- o:value("randomized") + o.default = "chrome" + o:depends({ [option_name("shadowtls")] = true, [option_name("shadowtls_utls")] = true }) +end + api.luci_types(arg[1], m, s, type_name, option_prefix) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua index a13d961a8..033b01227 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua @@ -41,8 +41,8 @@ o.datatype = "port" o = s:option(Flag, option_name("auth"), translate("Auth")) o.validate = function(self, value, t) if value and value == "1" then - local user_v = s.fields[option_name("username")]:formvalue(t) or "" - local pass_v = s.fields[option_name("password")]:formvalue(t) or "" + local user_v = s.fields[option_name("username")] and s.fields[option_name("username")]:formvalue(t) or "" + local pass_v = s.fields[option_name("password")] and s.fields[option_name("password")]:formvalue(t) or "" if user_v == "" or pass_v == "" then return nil, translate("Username and Password must be used together!") end @@ -115,11 +115,11 @@ o = s:option(Flag, option_name("tls"), translate("TLS")) o.default = 0 o.validate = function(self, value, t) if value then - local reality = s.fields[option_name("reality")]:formvalue(t) + local reality = s.fields[option_name("reality")] and s.fields[option_name("reality")]:formvalue(t) or nil if reality and reality == "1" then return value end if value == "1" then - local ca = s.fields[option_name("tls_certificateFile")]:formvalue(t) or "" - local key = s.fields[option_name("tls_keyFile")]:formvalue(t) or "" + local ca = s.fields[option_name("tls_certificateFile")] and s.fields[option_name("tls_certificateFile")]:formvalue(t) or "" + local key = s.fields[option_name("tls_keyFile")] and s.fields[option_name("tls_keyFile")]:formvalue(t) or "" if ca == "" or key == "" then return nil, translate("Public key and Private key path can not be empty!") end diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua index 310e0e79f..28bcb185c 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua @@ -53,8 +53,8 @@ o.datatype = "port" o = s:option(Flag, option_name("auth"), translate("Auth")) o.validate = function(self, value, t) if value and value == "1" then - local user_v = s.fields[option_name("username")]:formvalue(t) or "" - local pass_v = s.fields[option_name("password")]:formvalue(t) or "" + local user_v = s.fields[option_name("username")] and s.fields[option_name("username")]:formvalue(t) or "" + local pass_v = s.fields[option_name("password")] and s.fields[option_name("password")]:formvalue(t) or "" if user_v == "" or pass_v == "" then return nil, translate("Username and Password must be used together!") end @@ -202,11 +202,11 @@ o = s:option(Flag, option_name("tls"), translate("TLS")) o.default = 0 o.validate = function(self, value, t) if value then - local reality = s.fields[option_name("reality")]:formvalue(t) + local reality = s.fields[option_name("reality")] and s.fields[option_name("reality")]:formvalue(t) or nil if reality and reality == "1" then return value end if value == "1" then - local ca = s.fields[option_name("tls_certificateFile")]:formvalue(t) or "" - local key = s.fields[option_name("tls_keyFile")]:formvalue(t) or "" + local ca = s.fields[option_name("tls_certificateFile")] and s.fields[option_name("tls_certificateFile")]:formvalue(t) or "" + local key = s.fields[option_name("tls_keyFile")] and s.fields[option_name("tls_keyFile")]:formvalue(t) or "" if ca == "" or key == "" then return nil, translate("Public key and Private key path can not be empty!") end diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua index b5af55ac4..9b535febb 100644 --- a/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/luci-app-passwall2/luasrc/passwall2/api.lua @@ -922,9 +922,18 @@ function to_move(app_name,file) end function luci_types(id, m, s, type_name, option_prefix) + local rewrite_option_table = {} for key, value in pairs(s.fields) do if key:find(option_prefix) == 1 then if not s.fields[key].not_rewrite then + if s.fields[key].rewrite_option then + if not rewrite_option_table[s.fields[key].rewrite_option] then + rewrite_option_table[s.fields[key].rewrite_option] = 1 + else + rewrite_option_table[s.fields[key].rewrite_option] = rewrite_option_table[s.fields[key].rewrite_option] + 1 + end + end + s.fields[key].cfgvalue = function(self, section) if self.rewrite_option then return m:get(section, self.rewrite_option) @@ -947,7 +956,7 @@ function luci_types(id, m, s, type_name, option_prefix) end s.fields[key].remove = function(self, section) if s.fields["type"]:formvalue(id) == type_name then - if self.rewrite_option then + if self.rewrite_option and rewrite_option_table[self.rewrite_option] == 1 then m:del(section, self.rewrite_option) else if self.option:find(option_prefix) == 1 then diff --git a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index d8e71b1f4..0f9f30df6 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -814,6 +814,27 @@ function gen_config(var) elseif preproxy_node and api.is_normal_node(preproxy_node) then local preproxy_outbound = gen_outbound(flag, preproxy_node, preproxy_tag) if preproxy_outbound then + if preproxy_node.shadowtls == "1" then + local _node = { + type = "sing-box", + protocol = "shadowtls", + shadowtls_version = preproxy_node.shadowtls_version, + password = (preproxy_node.shadowtls_version == "2" or preproxy_node.shadowtls_version == "3") and preproxy_node.shadowtls_password or nil, + address = preproxy_node.address, + port = preproxy_node.port, + tls = "1", + tls_serverName = preproxy_node.shadowtls_serverName, + utls = preproxy_node.shadowtls_utls, + fingerprint = preproxy_node.shadowtls_fingerprint + } + local shadowtls_outbound = gen_outbound(flag, _node, preproxy_tag .. "_shadowtls") + if shadowtls_outbound then + table.insert(outbounds, shadowtls_outbound) + preproxy_outbound.detour = preproxy_outbound.tag .. "_shadowtls" + preproxy_outbound.server = nil + preproxy_outbound.server_port = nil + end + end table.insert(outbounds, preproxy_outbound) else preproxy_enabled = false @@ -895,8 +916,28 @@ function gen_config(var) end local _outbound = gen_outbound(flag, _node, rule_name, { proxy = proxy and 1 or 0, tag = proxy and preproxy_tag or nil }) if _outbound then + if _node.shadowtls == "1" then + local shadowtls_node = { + type = "sing-box", + protocol = "shadowtls", + shadowtls_version = _node.shadowtls_version, + password = (_node.shadowtls_version == "2" or _node.shadowtls_version == "3") and _node.shadowtls_password or nil, + address = _node.address, + port = _node.port, + tls = "1", + tls_serverName = _node.shadowtls_serverName, + utls = _node.shadowtls_utls, + fingerprint = _node.shadowtls_fingerprint + } + local shadowtls_outbound = gen_outbound(flag, shadowtls_node, rule_name .. "_shadowtls", { proxy = proxy and 1 or 0, tag = proxy and preproxy_tag or nil }) + if shadowtls_outbound then + table.insert(outbounds, shadowtls_outbound) + _outbound.detour = _outbound.tag .. "_shadowtls" + _outbound.server = nil + _outbound.server_port = nil + end + end table.insert(outbounds, _outbound) - if proxy then preproxy_used = true end rule_outboundTag = rule_name end end @@ -1065,6 +1106,29 @@ function gen_config(var) end else outbound = gen_outbound(flag, node) + if outbound then + if node.shadowtls == "1" then + local shadowtls_node = { + type = "sing-box", + protocol = "shadowtls", + shadowtls_version = node.shadowtls_version, + password = (node.shadowtls_version == "2" or node.shadowtls_version == "3") and node.shadowtls_password or nil, + address = node.address, + port = node.port, + tls = "1", + tls_serverName = node.shadowtls_serverName, + utls = node.shadowtls_utls, + fingerprint = node.shadowtls_fingerprint + } + local shadowtls_outbound = gen_outbound(flag, shadowtls_node, outbound.tag .. "_shadowtls") + if shadowtls_outbound then + table.insert(outbounds, shadowtls_outbound) + outbound.detour = outbound.tag .. "_shadowtls" + outbound.server = nil + outbound.server_port = nil + end + end + end end if outbound then default_outTag = outbound.tag