From 36c6425b3f02cdc08d76fdb026692fae3e2a29ff Mon Sep 17 00:00:00 2001 From: nftbty Date: Wed, 22 Mar 2023 08:55:34 +0800 Subject: [PATCH] luci: unified code style (#2395) * luci: unified code style - checked newline at end of file - unified indent - removed whitespaces at end of line * luci: change the indentation of lua files to tabs --- .../luasrc/model/cbi/passwall/client/acl.lua | 54 +- .../model/cbi/passwall/client/acl_config.lua | 236 +- .../model/cbi/passwall/client/app_update.lua | 14 +- .../model/cbi/passwall/client/auto_switch.lua | 24 +- .../model/cbi/passwall/client/global.lua | 342 +-- .../model/cbi/passwall/client/haproxy.lua | 60 +- .../model/cbi/passwall/client/node_config.lua | 156 +- .../model/cbi/passwall/client/node_list.lua | 186 +- .../cbi/passwall/client/node_subscribe.lua | 90 +- .../passwall/client/node_subscribe_config.lua | 40 +- .../model/cbi/passwall/client/other.lua | 102 +- .../luasrc/model/cbi/passwall/client/rule.lua | 46 +- .../model/cbi/passwall/client/rule_list.lua | 238 +- .../model/cbi/passwall/client/shunt_rules.lua | 70 +- .../model/cbi/passwall/server/index.lua | 47 +- .../luasrc/model/cbi/passwall/server/user.lua | 158 +- luci-app-passwall/luasrc/passwall/api.lua | 1194 ++++----- luci-app-passwall/luasrc/passwall/com.lua | 144 +- .../luasrc/passwall/server_app.lua | 368 +-- .../luasrc/passwall/util_hysteria.lua | 199 +- .../luasrc/passwall/util_naiveproxy.lua | 48 +- .../luasrc/passwall/util_shadowsocks.lua | 244 +- .../luasrc/passwall/util_trojan.lua | 282 +-- .../luasrc/passwall/util_xray.lua | 2234 ++++++++--------- .../view/passwall/app_update/app_version.htm | 3 +- .../view/passwall/auto_switch/footer.htm | 3 +- .../luasrc/view/passwall/global/faq.htm | 6 +- .../luasrc/view/passwall/global/footer.htm | 20 +- .../luasrc/view/passwall/global/status.htm | 8 +- .../luasrc/view/passwall/haproxy/status.htm | 2 +- .../luasrc/view/passwall/log/log.htm | 1 + .../view/passwall/node_list/link_add_node.htm | 14 +- .../passwall/node_list/link_share_man.htm | 61 +- .../view/passwall/node_list/node_list.htm | 58 +- .../luasrc/view/passwall/server/log.htm | 3 +- .../passwall/server/users_list_status.htm | 4 +- .../usr/share/passwall/helper_dnsmasq_add.lua | 592 ++--- .../root/usr/share/passwall/rule_update.lua | 24 +- 38 files changed, 3688 insertions(+), 3687 deletions(-) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua index 3b449b50c..518806724 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl.lua @@ -22,12 +22,12 @@ s.anonymous = true s.addremove = true s.extedit = api.url("acl_config", "%s") function s.create(e, t) - t = TypedSection.create(e, t) - luci.http.redirect(e.extedit:format(t)) + t = TypedSection.create(e, t) + luci.http.redirect(e.extedit:format(t)) end function s.remove(e, t) - sys.call("rm -rf /tmp/etc/passwall_tmp/dns_" .. t .. "*") - TypedSection.remove(e, t) + sys.call("rm -rf /tmp/etc/passwall_tmp/dns_" .. t .. "*") + TypedSection.remove(e, t) end ---- Enable @@ -41,28 +41,28 @@ o.rmempty = true local mac_t = {} sys.net.mac_hints(function(e, t) - mac_t[e] = { - ip = t, - mac = e - } + mac_t[e] = { + ip = t, + mac = e + } end) o = s:option(DummyValue, "sources", translate("Source")) o.rawhtml = true o.cfgvalue = function(t, n) - local e = '' - local v = Value.cfgvalue(t, n) or '' - string.gsub(v, '[^' .. " " .. ']+', function(w) - local a = w - if mac_t[w] then - a = a .. ' (' .. mac_t[w].ip .. ')' - end - if #e > 0 then - e = e .. "
" - end - e = e .. a - end) - return e + local e = '' + local v = Value.cfgvalue(t, n) or '' + string.gsub(v, '[^' .. " " .. ']+', function(w) + local a = w + if mac_t[w] then + a = a .. ' (' .. mac_t[w].ip .. ')' + end + if #e > 0 then + e = e .. "
" + end + e = e .. a + end) + return e end ---- TCP Proxy Mode @@ -73,10 +73,10 @@ tcp_proxy_mode:value("default", translate("Default")) tcp_proxy_mode:value("disable", translate("No Proxy")) tcp_proxy_mode:value("global", translate("Global Proxy")) if has_chnlist and global_proxy_mode:find("returnhome") then - tcp_proxy_mode:value("returnhome", translate("China List")) + tcp_proxy_mode:value("returnhome", translate("China List")) else - tcp_proxy_mode:value("gfwlist", translate("GFW List")) - tcp_proxy_mode:value("chnroute", translate("Not China List")) + tcp_proxy_mode:value("gfwlist", translate("GFW List")) + tcp_proxy_mode:value("chnroute", translate("Not China List")) end tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) @@ -88,10 +88,10 @@ udp_proxy_mode:value("default", translate("Default")) udp_proxy_mode:value("disable", translate("No Proxy")) udp_proxy_mode:value("global", translate("Global Proxy")) if has_chnlist and global_proxy_mode:find("returnhome") then - udp_proxy_mode:value("returnhome", translate("China List")) + udp_proxy_mode:value("returnhome", translate("China List")) else - udp_proxy_mode:value("gfwlist", translate("GFW List")) - udp_proxy_mode:value("chnroute", translate("Not China List")) + udp_proxy_mode:value("gfwlist", translate("GFW List")) + udp_proxy_mode:value("chnroute", translate("Not China List")) end udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua index 159396c1e..ec43df18e 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/acl_config.lua @@ -9,28 +9,28 @@ m = Map(appname) local nodes_table = {} for k, e in ipairs(api.get_valid_nodes()) do - nodes_table[#nodes_table + 1] = e + nodes_table[#nodes_table + 1] = e end local global_proxy_mode = (m:get("@global[0]", "tcp_proxy_mode") or "") .. (m:get("@global[0]", "udp_proxy_mode") or "") local dynamicList_write = function(self, section, value) - local t = {} - local t2 = {} - if type(value) == "table" then + local t = {} + local t2 = {} + if type(value) == "table" then local x for _, x in ipairs(value) do if x and #x > 0 then - if not t2[x] then - t2[x] = x - t[#t+1] = x - end + if not t2[x] then + t2[x] = x + t[#t+1] = x + end end end else t = { value } end - t = table.concat(t, " ") + t = table.concat(t, " ") return DynamicList.write(self, section, t) end @@ -51,22 +51,22 @@ o.rmempty = true local mac_t = {} sys.net.mac_hints(function(e, t) - mac_t[#mac_t + 1] = { - ip = t, - mac = e - } + mac_t[#mac_t + 1] = { + ip = t, + mac = e + } end) table.sort(mac_t, function(a,b) - if #a.ip < #b.ip then - return true - elseif #a.ip == #b.ip then - if a.ip < b.ip then - return true - else - return #a.ip < #b.ip - end - end - return false + if #a.ip < #b.ip then + return true + elseif #a.ip == #b.ip then + if a.ip < b.ip then + return true + else + return #a.ip < #b.ip + end + end + return false end) ---- Source @@ -80,58 +80,58 @@ sources.description = "" sources.cast = "string" for _, key in pairs(mac_t) do - sources:value(key.mac, "%s (%s)" % {key.mac, key.ip}) + sources:value(key.mac, "%s (%s)" % {key.mac, key.ip}) end sources.cfgvalue = function(self, section) - local value + local value if self.tag_error[section] then value = self:formvalue(section) else value = self.map:get(section, self.option) - if type(value) == "string" then - local value2 = {} - string.gsub(value, '[^' .. " " .. ']+', function(w) table.insert(value2, w) end) - value = value2 - end + if type(value) == "string" then + local value2 = {} + string.gsub(value, '[^' .. " " .. ']+', function(w) table.insert(value2, w) end) + value = value2 + end end - return value + return value end sources.validate = function(self, value, t) - local err = {} - for _, v in ipairs(value) do - local flag = false - if v:find("ipset:") and v:find("ipset:") == 1 then - local ipset = v:gsub("ipset:", "") - if ipset and ipset ~= "" then - flag = true - end - end + local err = {} + for _, v in ipairs(value) do + local flag = false + if v:find("ipset:") and v:find("ipset:") == 1 then + local ipset = v:gsub("ipset:", "") + if ipset and ipset ~= "" then + flag = true + end + end - if flag == false and datatypes.macaddr(v) then - flag = true - end + if flag == false and datatypes.macaddr(v) then + flag = true + end - if flag == false and datatypes.ip4addr(v) then - flag = true - end + if flag == false and datatypes.ip4addr(v) then + flag = true + end - if flag == false and api.iprange(v) then - flag = true - end + if flag == false and api.iprange(v) then + flag = true + end - if flag == false then - err[#err + 1] = v - end - end + if flag == false then + err[#err + 1] = v + end + end - if #err > 0 then - self:add_error(t, "invalid", translate("Not true format, please re-enter!")) - for _, v in ipairs(err) do - self:add_error(t, "invalid", v) - end - end + if #err > 0 then + self:add_error(t, "invalid", translate("Not true format, please re-enter!")) + for _, v in ipairs(err) do + self:add_error(t, "invalid", v) + end + end - return value + return value end sources.write = dynamicList_write @@ -186,10 +186,10 @@ tcp_proxy_mode:value("default", translate("Default")) tcp_proxy_mode:value("disable", translate("No Proxy")) tcp_proxy_mode:value("global", translate("Global Proxy")) if has_chnlist and global_proxy_mode:find("returnhome") then - tcp_proxy_mode:value("returnhome", translate("China List")) + tcp_proxy_mode:value("returnhome", translate("China List")) else - tcp_proxy_mode:value("gfwlist", translate("GFW List")) - tcp_proxy_mode:value("chnroute", translate("Not China List")) + tcp_proxy_mode:value("gfwlist", translate("GFW List")) + tcp_proxy_mode:value("chnroute", translate("Not China List")) end tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) @@ -201,10 +201,10 @@ udp_proxy_mode:value("default", translate("Default")) udp_proxy_mode:value("disable", translate("No Proxy")) udp_proxy_mode:value("global", translate("Global Proxy")) if has_chnlist and global_proxy_mode:find("returnhome") then - udp_proxy_mode:value("returnhome", translate("China List")) + udp_proxy_mode:value("returnhome", translate("China List")) else - udp_proxy_mode:value("gfwlist", translate("GFW List")) - udp_proxy_mode:value("chnroute", translate("Not China List")) + udp_proxy_mode:value("gfwlist", translate("GFW List")) + udp_proxy_mode:value("chnroute", translate("Not China List")) end udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) @@ -218,8 +218,8 @@ udp_node:value("default", translate("Default")) udp_node:value("tcp", translate("Same as the tcp node")) for k, v in pairs(nodes_table) do - tcp_node:value(v.id, v["remark"]) - udp_node:value(v.id, v["remark"]) + tcp_node:value(v.id, v["remark"]) + udp_node:value(v.id, v["remark"]) end o = s:option(Flag, "filter_proxy_ipv6", translate("Filter Proxy Host IPv6"), translate("Experimental feature.")) @@ -230,10 +230,10 @@ o:depends({ tcp_node = "default", ['!reverse'] = true }) o = s:option(ListValue, "dns_mode", translate("Filter Mode")) o:depends({ tcp_node = "default", ['!reverse'] = true }) if api.is_finded("dns2socks") then - o:value("dns2socks", "dns2socks") + o:value("dns2socks", "dns2socks") end if has_xray then - o:value("xray", "Xray") + o:value("xray", "Xray") end o = s:option(ListValue, "v2ray_dns_mode", " ") @@ -255,40 +255,40 @@ o:depends("dns_mode", "dns2socks") o:depends("v2ray_dns_mode", "tcp") if has_v2ray or has_xray then - o = s:option(Value, "remote_dns_doh", translate("Remote DNS DoH")) - o:value("https://1.1.1.1/dns-query", "CloudFlare") - o:value("https://1.1.1.2/dns-query", "CloudFlare-Security") - o:value("https://8.8.4.4/dns-query", "Google 8844") - o:value("https://8.8.8.8/dns-query", "Google 8888") - o:value("https://9.9.9.9/dns-query", "Quad9-Recommended") - o:value("https://208.67.222.222/dns-query", "OpenDNS") - o:value("https://dns.adguard.com/dns-query,176.103.130.130", "AdGuard") - o:value("https://doh.libredns.gr/dns-query,116.202.176.26", "LibreDNS") - o:value("https://doh.libredns.gr/ads,116.202.176.26", "LibreDNS (No Ads)") - o.default = "https://1.1.1.1/dns-query" - o.validate = function(self, value, t) - if value ~= "" then - value = api.trim(value) - local flag = 0 - local util = require "luci.util" - local val = util.split(value, ",") - local url = val[1] - val[1] = nil - for i = 1, #val do - local v = val[i] - if v then - if not api.datatypes.ipmask4(v) then - flag = 1 - end - end - end - if flag == 0 then - return value - end - end - return nil, translate("DoH request address") .. " " .. translate("Format must be:") .. " URL,IP" - end - o:depends("v2ray_dns_mode", "doh") + o = s:option(Value, "remote_dns_doh", translate("Remote DNS DoH")) + o:value("https://1.1.1.1/dns-query", "CloudFlare") + o:value("https://1.1.1.2/dns-query", "CloudFlare-Security") + o:value("https://8.8.4.4/dns-query", "Google 8844") + o:value("https://8.8.8.8/dns-query", "Google 8888") + o:value("https://9.9.9.9/dns-query", "Quad9-Recommended") + o:value("https://208.67.222.222/dns-query", "OpenDNS") + o:value("https://dns.adguard.com/dns-query,176.103.130.130", "AdGuard") + o:value("https://doh.libredns.gr/dns-query,116.202.176.26", "LibreDNS") + o:value("https://doh.libredns.gr/ads,116.202.176.26", "LibreDNS (No Ads)") + o.default = "https://1.1.1.1/dns-query" + o.validate = function(self, value, t) + if value ~= "" then + value = api.trim(value) + local flag = 0 + local util = require "luci.util" + local val = util.split(value, ",") + local url = val[1] + val[1] = nil + for i = 1, #val do + local v = val[i] + if v then + if not api.datatypes.ipmask4(v) then + flag = 1 + end + end + end + if flag == 0 then + return value + end + end + return nil, translate("DoH request address") .. " " .. translate("Format must be:") .. " URL,IP" + end + o:depends("v2ray_dns_mode", "doh") end o = s:option(Value, "dns_client_ip", translate("EDNS Client Subnet")) @@ -296,20 +296,20 @@ o.datatype = "ipaddr" o:depends("v2ray_dns_mode", "doh") if has_chnlist then - when_chnroute_default_dns = s:option(ListValue, "when_chnroute_default_dns", translate("When using the chnroute list the default DNS")) - when_chnroute_default_dns.default = "direct" - when_chnroute_default_dns:value("remote", translate("Remote DNS")) - when_chnroute_default_dns:value("direct", translate("Direct DNS")) - when_chnroute_default_dns.description = "" - when_chnroute_default_dns:depends("tcp_proxy_mode", "chnroute") - when_chnroute_default_dns:depends("udp_proxy_mode", "chnroute") + when_chnroute_default_dns = s:option(ListValue, "when_chnroute_default_dns", translate("When using the chnroute list the default DNS")) + when_chnroute_default_dns.default = "direct" + when_chnroute_default_dns:value("remote", translate("Remote DNS")) + when_chnroute_default_dns:value("direct", translate("Direct DNS")) + when_chnroute_default_dns.description = "" + when_chnroute_default_dns:depends("tcp_proxy_mode", "chnroute") + when_chnroute_default_dns:depends("udp_proxy_mode", "chnroute") end return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua index 7da1af06d..1d3e9addf 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/app_update.lua @@ -5,24 +5,24 @@ m = Map(appname) -- [[ App Settings ]]-- s = m:section(TypedSection, "global_app", translate("App Update"), - "" .. - translate("Please confirm that your firmware supports FPU.") .. - "") + "" .. + translate("Please confirm that your firmware supports FPU.") .. + "") s.anonymous = true s:append(Template(appname .. "/app_update/app_version")) local k, v local com = require "luci.passwall.com" for k, v in pairs(com) do - o = s:option(Value, k:gsub("%-","_") .. "_file", translatef("%s App Path", v.name)) - o.default = v.default_path or ("/usr/bin/"..k) - o.rmempty = false + o = s:option(Value, k:gsub("%-","_") .. "_file", translatef("%s App Path", v.name)) + o.default = v.default_path or ("/usr/bin/"..k) + o.rmempty = false end o = s:option(DummyValue, "tips", " ") o.rawhtml = true o.cfgvalue = function(t, n) - return string.format('%s', translate("if you want to run from memory, change the path, /tmp beginning then save the application and update it manually.")) + return string.format('%s', translate("if you want to run from memory, change the path, /tmp beginning then save the application and update it manually.")) end return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua index e628ab3ce..546170dff 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua @@ -3,7 +3,7 @@ local appname = api.appname local nodes_table = {} for k, e in ipairs(api.get_valid_nodes()) do - nodes_table[#nodes_table + 1] = e + nodes_table[#nodes_table + 1] = e end m = Map(appname) @@ -28,24 +28,24 @@ o.default = 3 o = s:option(Value, "retry_num", translate("Timeout retry num")) o.datatype = "uinteger" o.default = 3 - + o = s:option(DynamicList, "tcp_node", "TCP " .. translate("List of backup nodes")) for k, v in pairs(nodes_table) do - if v.node_type == "normal" then - o:value(v.id, v["remark"]) - end + if v.node_type == "normal" then + o:value(v.id, v["remark"]) + end end function o.write(self, section, value) - local t = {} - local t2 = {} - if type(value) == "table" then + local t = {} + local t2 = {} + if type(value) == "table" then local x for _, x in ipairs(value) do if x and #x > 0 then - if not t2[x] then - t2[x] = x - t[#t+1] = x - end + if not t2[x] then + t2[x] = x + t[#t+1] = x + end end end else diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua index e875d5aaa..8d067c1de 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -10,66 +10,66 @@ m = Map(appname) local nodes_table = {} for k, e in ipairs(api.get_valid_nodes()) do - nodes_table[#nodes_table + 1] = e + nodes_table[#nodes_table + 1] = e end local tcp_socks_server = "127.0.0.1" .. ":" .. (uci:get(appname, "@global[0]", "tcp_node_socks_port") or "1070") local socks_table = {} socks_table[#socks_table + 1] = { - id = tcp_socks_server, - remarks = tcp_socks_server .. " - " .. translate("TCP Node") + id = tcp_socks_server, + remarks = tcp_socks_server .. " - " .. translate("TCP Node") } uci:foreach(appname, "socks", function(s) - if s.enabled == "1" and s.node then - local id, remarks - for k, n in pairs(nodes_table) do - if (s.node == n.id) then - remarks = n["remark"]; break - end - end - id = "127.0.0.1" .. ":" .. s.port - socks_table[#socks_table + 1] = { - id = id, - remarks = id .. " - " .. (remarks or translate("Misconfigured")) - } - end + if s.enabled == "1" and s.node then + local id, remarks + for k, n in pairs(nodes_table) do + if (s.node == n.id) then + remarks = n["remark"]; break + end + end + id = "127.0.0.1" .. ":" .. s.port + socks_table[#socks_table + 1] = { + id = id, + remarks = id .. " - " .. (remarks or translate("Misconfigured")) + } + end end) local doh_validate = function(self, value, t) - if value ~= "" then - value = api.trim(value) - local flag = 0 - local util = require "luci.util" - local val = util.split(value, ",") - local url = val[1] - val[1] = nil - for i = 1, #val do - local v = val[i] - if v then - if not datatypes.ipmask4(v) then - flag = 1 - end - end - end - if flag == 0 then - return value - end - end - return nil, translate("DoH request address") .. " " .. translate("Format must be:") .. " URL,IP" + if value ~= "" then + value = api.trim(value) + local flag = 0 + local util = require "luci.util" + local val = util.split(value, ",") + local url = val[1] + val[1] = nil + for i = 1, #val do + local v = val[i] + if v then + if not datatypes.ipmask4(v) then + flag = 1 + end + end + end + if flag == 0 then + return value + end + end + return nil, translate("DoH request address") .. " " .. translate("Format must be:") .. " URL,IP" end local redir_mode_validate = function(self, value, t) - local tcp_proxy_mode_v = tcp_proxy_mode:formvalue(t) or "" - local udp_proxy_mode_v = udp_proxy_mode:formvalue(t) or "" - local localhost_tcp_proxy_mode_v = localhost_tcp_proxy_mode:formvalue(t) or "" - local localhost_udp_proxy_mode_v = localhost_udp_proxy_mode:formvalue(t) or "" - local s = tcp_proxy_mode_v .. udp_proxy_mode_v .. localhost_tcp_proxy_mode_v .. localhost_udp_proxy_mode_v - if s:find("returnhome") then - if s:find("chnroute") or s:find("gfwlist") then - return nil, translate("China list or gfwlist cannot be used together with outside China list!") - end - end - return value + local tcp_proxy_mode_v = tcp_proxy_mode:formvalue(t) or "" + local udp_proxy_mode_v = udp_proxy_mode:formvalue(t) or "" + local localhost_tcp_proxy_mode_v = localhost_tcp_proxy_mode:formvalue(t) or "" + local localhost_udp_proxy_mode_v = localhost_udp_proxy_mode:formvalue(t) or "" + local s = tcp_proxy_mode_v .. udp_proxy_mode_v .. localhost_tcp_proxy_mode_v .. localhost_udp_proxy_mode_v + if s:find("returnhome") then + if s:find("chnroute") or s:find("gfwlist") then + return nil, translate("China list or gfwlist cannot be used together with outside China list!") + end + end + return value end m:append(Template(appname .. "/global/status")) @@ -89,80 +89,80 @@ tcp_node = s:taboption("Main", ListValue, "tcp_node", "" . tcp_node.description = "" local current_node = luci.sys.exec(string.format("[ -f '/tmp/etc/%s/id/TCP' ] && echo -n $(cat /tmp/etc/%s/id/TCP)", appname, appname)) if current_node and current_node ~= "" and current_node ~= "nil" then - local n = uci:get_all(appname, current_node) - if n then - if tonumber(m:get("@auto_switch[0]", "enable") or 0) == 1 then - local remarks = api.get_full_node_remarks(n) - local url = api.url("node_config", current_node) - tcp_node.description = tcp_node.description .. translatef("Current node: %s", string.format('%s', url, remarks)) .. "
" - end - end + local n = uci:get_all(appname, current_node) + if n then + if tonumber(m:get("@auto_switch[0]", "enable") or 0) == 1 then + local remarks = api.get_full_node_remarks(n) + local url = api.url("node_config", current_node) + tcp_node.description = tcp_node.description .. translatef("Current node: %s", string.format('%s', url, remarks)) .. "
" + end + end end tcp_node:value("nil", translate("Close")) -- 分流 if (has_v2ray or has_xray) and #nodes_table > 0 then - local normal_list = {} - local shunt_list = {} - for k, v in pairs(nodes_table) do - if v.node_type == "normal" then - normal_list[#normal_list + 1] = v - end - if v.protocol and v.protocol == "_shunt" then - shunt_list[#shunt_list + 1] = v - end - end - for k, v in pairs(shunt_list) do - uci:foreach(appname, "shunt_rules", function(e) - local id = e[".name"] - if id and e.remarks then - o = s:taboption("Main", ListValue, v.id .. "." .. id .. "_node", string.format('* %s', api.url("shunt_rules", id), e.remarks)) - o:depends("tcp_node", v.id) - o:value("nil", translate("Close")) - o:value("_default", translate("Default")) - o:value("_direct", translate("Direct Connection")) - o:value("_blackhole", translate("Blackhole")) - for k1, v1 in pairs(normal_list) do - o:value(v1.id, v1["remark"]) - end - o.cfgvalue = function(self, section) - return m:get(v.id, id) or "nil" - end - o.write = function(self, section, value) - m:set(v.id, id, value) - end - end - end) + local normal_list = {} + local shunt_list = {} + for k, v in pairs(nodes_table) do + if v.node_type == "normal" then + normal_list[#normal_list + 1] = v + end + if v.protocol and v.protocol == "_shunt" then + shunt_list[#shunt_list + 1] = v + end + end + for k, v in pairs(shunt_list) do + uci:foreach(appname, "shunt_rules", function(e) + local id = e[".name"] + if id and e.remarks then + o = s:taboption("Main", ListValue, v.id .. "." .. id .. "_node", string.format('* %s', api.url("shunt_rules", id), e.remarks)) + o:depends("tcp_node", v.id) + o:value("nil", translate("Close")) + o:value("_default", translate("Default")) + o:value("_direct", translate("Direct Connection")) + o:value("_blackhole", translate("Blackhole")) + for k1, v1 in pairs(normal_list) do + o:value(v1.id, v1["remark"]) + end + o.cfgvalue = function(self, section) + return m:get(v.id, id) or "nil" + end + o.write = function(self, section, value) + m:set(v.id, id, value) + end + end + end) - local id = "default_node" - o = s:taboption("Main", ListValue, v.id .. "." .. id, string.format('* %s', translate("Default"))) - o:depends("tcp_node", v.id) - o:value("_direct", translate("Direct Connection")) - o:value("_blackhole", translate("Blackhole")) - for k1, v1 in pairs(normal_list) do - o:value(v1.id, v1["remark"]) - end - o.cfgvalue = function(self, section) - return m:get(v.id, id) or "nil" - end - o.write = function(self, section, value) - m:set(v.id, id, value) - end - - local id = "main_node" - o = s:taboption("Main", ListValue, v.id .. "." .. id, string.format('* %s', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node.")) - o:depends("tcp_node", v.id) - o:value("nil", translate("Close")) - for k1, v1 in pairs(normal_list) do - o:value(v1.id, v1["remark"]) - end - o.cfgvalue = function(self, section) - return m:get(v.id, id) or "nil" - end - o.write = function(self, section, value) - m:set(v.id, id, value) - end - end + local id = "default_node" + o = s:taboption("Main", ListValue, v.id .. "." .. id, string.format('* %s', translate("Default"))) + o:depends("tcp_node", v.id) + o:value("_direct", translate("Direct Connection")) + o:value("_blackhole", translate("Blackhole")) + for k1, v1 in pairs(normal_list) do + o:value(v1.id, v1["remark"]) + end + o.cfgvalue = function(self, section) + return m:get(v.id, id) or "nil" + end + o.write = function(self, section, value) + m:set(v.id, id, value) + end + + local id = "main_node" + o = s:taboption("Main", ListValue, v.id .. "." .. id, string.format('* %s', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node.")) + o:depends("tcp_node", v.id) + o:value("nil", translate("Close")) + for k1, v1 in pairs(normal_list) do + o:value(v1.id, v1["remark"]) + end + o.cfgvalue = function(self, section) + return m:get(v.id, id) or "nil" + end + o.write = function(self, section, value) + m:set(v.id, id, value) + end + end end udp_node = s:taboption("Main", ListValue, "udp_node", "" .. translate("UDP Node") .. "") @@ -175,9 +175,9 @@ tcp_node_socks_port.datatype = "port" --[[ if has_v2ray or has_xray then - tcp_node_http_port = s:taboption("Main", Value, "tcp_node_http_port", translate("TCP Node") .. " HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use")) - tcp_node_http_port.default = 0 - tcp_node_http_port.datatype = "port" + tcp_node_http_port = s:taboption("Main", Value, "tcp_node_http_port", translate("TCP Node") .. " HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use")) + tcp_node_http_port.default = 0 + tcp_node_http_port.datatype = "port" end ]]-- @@ -192,13 +192,13 @@ dns_mode = s:taboption("DNS", ListValue, "dns_mode", translate("Filter Mode")) dns_mode.rmempty = false dns_mode:reset_values() if api.is_finded("dns2tcp") then - dns_mode:value("dns2tcp", translatef("Requery DNS By %s", "TCP")) + dns_mode:value("dns2tcp", translatef("Requery DNS By %s", "TCP")) end if api.is_finded("dns2socks") then - dns_mode:value("dns2socks", "dns2socks") + dns_mode:value("dns2socks", "dns2socks") end if has_xray then - dns_mode:value("xray", "Xray") + dns_mode:value("xray", "Xray") end dns_mode:value("udp", translatef("Requery DNS By %s", "UDP")) @@ -208,24 +208,24 @@ o:value("doh", "DoH") o:value("fakedns", "FakeDNS") o:depends("dns_mode", "xray") o.validate = function(self, value, t) - if value == "fakedns" then - local _dns_mode = dns_mode:formvalue(t) - local _tcp_node = tcp_node:formvalue(t) - if m:get(_tcp_node, "type"):lower() ~= _dns_mode then - return nil, translatef("TCP node must be '%s' type to use FakeDNS.", _dns_mode) - end - end - return value + if value == "fakedns" then + local _dns_mode = dns_mode:formvalue(t) + local _tcp_node = tcp_node:formvalue(t) + if m:get(_tcp_node, "type"):lower() ~= _dns_mode then + return nil, translatef("TCP node must be '%s' type to use FakeDNS.", _dns_mode) + end + end + return value end o = s:taboption("DNS", Value, "socks_server", translate("Socks Server"), translate("Make sure socks service is available on this address.")) for k, v in pairs(socks_table) do o:value(v.id, v.remarks) end o.default = socks_table[1].id o.validate = function(self, value, t) - if not datatypes.ipaddrport(value) then - return nil, translate("Socks Server") .. " " .. translate("Not valid IP format, please re-enter!") - end - return value + if not datatypes.ipaddrport(value) then + return nil, translate("Socks Server") .. " " .. translate("Not valid IP format, please re-enter!") + end + return value end o:depends({dns_mode = "dns2socks"}) @@ -263,7 +263,7 @@ o:depends("v2ray_dns_mode", "doh") o = s:taboption("DNS", Value, "dns_client_ip", translate("EDNS Client Subnet")) o.description = translate("Notify the DNS server when the DNS query is notified, the location of the client (cannot be a private IP address).") .. "
" .. - translate("This feature requires the DNS server to support the Edns Client Subnet (RFC7871).") + translate("This feature requires the DNS server to support the Edns Client Subnet (RFC7871).") o.datatype = "ipaddr" o:depends("v2ray_dns_mode", "tcp") o:depends("v2ray_dns_mode", "doh") @@ -276,25 +276,25 @@ o:depends({dns_mode = "xray", v2ray_dns_mode = "doh"}) o.rmempty = false if has_chnlist then - when_chnroute_default_dns = s:taboption("DNS", ListValue, "when_chnroute_default_dns", translate("When using the chnroute list the default DNS")) - when_chnroute_default_dns.default = "direct" - when_chnroute_default_dns:value("remote", translate("Remote DNS")) - when_chnroute_default_dns:value("direct", translate("Direct DNS")) - when_chnroute_default_dns.description = "" + when_chnroute_default_dns = s:taboption("DNS", ListValue, "when_chnroute_default_dns", translate("When using the chnroute list the default DNS")) + when_chnroute_default_dns.default = "direct" + when_chnroute_default_dns:value("remote", translate("Remote DNS")) + when_chnroute_default_dns:value("direct", translate("Direct DNS")) + when_chnroute_default_dns.description = "" end o = s:taboption("DNS", Button, "clear_ipset", translate("Clear IPSET"), translate("Try this feature if the rule modification does not take effect.")) o.inputstyle = "remove" function o.write(e, e) - luci.sys.call("[ -n \"$(nft list sets 2>/dev/null | grep \"gfwlist\")\" ] && /usr/share/" .. appname .. "/nftables.sh flush_nftset || /usr/share/" .. appname .. "/iptables.sh flush_ipset > /dev/null 2>&1 &") - luci.http.redirect(api.url("log")) + luci.sys.call("[ -n \"$(nft list sets 2>/dev/null | grep \"gfwlist\")\" ] && /usr/share/" .. appname .. "/nftables.sh flush_nftset || /usr/share/" .. appname .. "/iptables.sh flush_ipset > /dev/null 2>&1 &") + luci.http.redirect(api.url("log")) end s:tab("Proxy", translate("Mode")) @@ -306,7 +306,7 @@ tcp_proxy_mode:value("global", translate("Global Proxy")) tcp_proxy_mode:value("gfwlist", translate("GFW List")) tcp_proxy_mode:value("chnroute", translate("Not China List")) if has_chnlist then - tcp_proxy_mode:value("returnhome", translate("China List")) + tcp_proxy_mode:value("returnhome", translate("China List")) end tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) tcp_proxy_mode.default = "chnroute" @@ -319,7 +319,7 @@ udp_proxy_mode:value("global", translate("Global Proxy")) udp_proxy_mode:value("gfwlist", translate("GFW List")) udp_proxy_mode:value("chnroute", translate("Not China List")) if has_chnlist then - udp_proxy_mode:value("returnhome", translate("China List")) + udp_proxy_mode:value("returnhome", translate("China List")) end udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) udp_proxy_mode.default = "chnroute" @@ -332,7 +332,7 @@ localhost_tcp_proxy_mode:value("global", translate("Global Proxy")) localhost_tcp_proxy_mode:value("gfwlist", translate("GFW List")) localhost_tcp_proxy_mode:value("chnroute", translate("Not China List")) if has_chnlist then - localhost_tcp_proxy_mode:value("returnhome", translate("China List")) + localhost_tcp_proxy_mode:value("returnhome", translate("China List")) end localhost_tcp_proxy_mode:value("disable", translate("No Proxy")) localhost_tcp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) @@ -346,7 +346,7 @@ localhost_udp_proxy_mode:value("global", translate("Global Proxy")) localhost_udp_proxy_mode:value("gfwlist", translate("GFW List")) localhost_udp_proxy_mode:value("chnroute", translate("Not China List")) if has_chnlist then - localhost_udp_proxy_mode:value("returnhome", translate("China List")) + localhost_udp_proxy_mode:value("returnhome", translate("China List")) end localhost_udp_proxy_mode:value("disable", translate("No Proxy")) localhost_udp_proxy_mode:value("direct/proxy", translate("Only use direct/proxy list")) @@ -356,7 +356,7 @@ localhost_udp_proxy_mode.validate = redir_mode_validate tips = s:taboption("Proxy", DummyValue, "tips", " ") tips.rawhtml = true tips.cfgvalue = function(t, n) - return string.format('%s', api.url("acl"), translate("Want different devices to use different proxy modes/ports/nodes? Please use access control.")) + return string.format('%s', api.url("acl"), translate("Want different devices to use different proxy modes/ports/nodes? Please use access control.")) end s:tab("log", translate("Log")) @@ -395,13 +395,13 @@ s.anonymous = true s.addremove = true s.template = "cbi/tblsection" function s.create(e, t) - TypedSection.create(e, api.gen_uuid()) + TypedSection.create(e, api.gen_uuid()) end o = s:option(DummyValue, "status", translate("Status")) o.rawhtml = true o.cfgvalue = function(t, n) - return string.format('
', n) + return string.format('
', n) end ---- Enable @@ -413,10 +413,10 @@ socks_node = s:option(ListValue, "node", translate("Socks Node")) local n = 1 uci:foreach(appname, "socks", function(s) - if s[".name"] == section then - return false - end - n = n + 1 + if s[".name"] == section then + return false + end + n = n + 1 end) o = s:option(Value, "port", "Socks " .. translate("Listen Port")) @@ -425,21 +425,21 @@ o.datatype = "port" o.rmempty = false if has_v2ray or has_xray then - o = s:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use")) - o.default = 0 - o.datatype = "port" + o = s:option(Value, "http_port", "HTTP " .. translate("Listen Port") .. " " .. translate("0 is not use")) + o.default = 0 + o.datatype = "port" end for k, v in pairs(nodes_table) do - tcp_node:value(v.id, v["remark"]) - udp_node:value(v.id, v["remark"]) - if v.type == "Socks" then - if has_v2ray or has_xray then - socks_node:value(v.id, v["remark"]) - end - else - socks_node:value(v.id, v["remark"]) - end + tcp_node:value(v.id, v["remark"]) + udp_node:value(v.id, v["remark"]) + if v.type == "Socks" then + if has_v2ray or has_xray then + socks_node:value(v.id, v["remark"]) + end + else + socks_node:value(v.id, v["remark"]) + end end m:append(Template(appname .. "/global/footer")) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua index b60a1f735..111934582 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/haproxy.lua @@ -6,13 +6,13 @@ local datatypes = api.datatypes local nodes_table = {} for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" then - nodes_table[#nodes_table + 1] = { - id = e[".name"], - obj = e, - remarks = e["remark"] - } - end + if e.node_type == "normal" then + nodes_table[#nodes_table + 1] = { + id = e[".name"], + obj = e, + remarks = e["remark"] + } + end end m = Map(appname) @@ -41,31 +41,31 @@ o:depends("balancing_enable", true) ---- Console Port o = s:option(Value, "console_port", translate("Console Port"), translate( - "In the browser input routing IP plus port access, such as:192.168.1.1:1188")) + "In the browser input routing IP plus port access, such as:192.168.1.1:1188")) o.default = "1188" o:depends("balancing_enable", true) -- [[ Balancing Settings ]]-- s = m:section(TypedSection, "haproxy_config", "", - "" .. - translate("Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group.") .. - "\n" .. translate("Note that the node configuration parameters for load balancing must be consistent, otherwise problems can arise!") .. - "") + "" .. + translate("Add a node, Export Of Multi WAN Only support Multi Wan. Load specific gravity range 1-256. Multiple primary servers can be load balanced, standby will only be enabled when the primary server is offline! Multiple groups can be set, Haproxy port same one for each group.") .. + "\n" .. translate("Note that the node configuration parameters for load balancing must be consistent, otherwise problems can arise!") .. + "") s.template = "cbi/tblsection" s.sortable = true s.anonymous = true s.addremove = true s.create = function(e, t) - TypedSection.create(e, api.gen_uuid()) + TypedSection.create(e, api.gen_uuid()) end s.remove = function(self, section) - for k, v in pairs(self.children) do - v.rmempty = true - v.validate = nil - end - TypedSection.remove(self, section) + for k, v in pairs(self.children) do + v.rmempty = true + v.validate = nil + end + TypedSection.remove(self, section) end ---- Enable @@ -78,18 +78,18 @@ o = s:option(Value, "lbss", translate("Node Address")) for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end o.rmempty = false o.validate = function(self, value) - if not value then return nil end - local t = m:get(value) or nil - if t and t[".type"] == "nodes" then - return value - end - if datatypes.hostport(value) or datatypes.ip4addrport(value) then - return value - end - if api.is_ipv6addrport(value) then - return value - end - return nil, value + if not value then return nil end + local t = m:get(value) or nil + if t and t[".type"] == "nodes" then + return value + end + if datatypes.hostport(value) or datatypes.ip4addrport(value) then + return value + end + if api.is_ipv6addrport(value) then + return value + end + return nil, value end ---- Haproxy Port 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 058d0b12f..05ef2d43b 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 @@ -3,53 +3,53 @@ local appname = api.appname local uci = api.uci if not arg[1] or not uci:get(appname, arg[1]) then - luci.http.redirect(api.url("node_list")) + luci.http.redirect(api.url("node_list")) end local ss_encrypt_method_list = { - "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", - "aes-192-ctr", "aes-256-ctr", "bf-cfb", "salsa20", "chacha20", "chacha20-ietf", - "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305" + "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", + "aes-192-ctr", "aes-256-ctr", "bf-cfb", "salsa20", "chacha20", "chacha20-ietf", + "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", + "xchacha20-ietf-poly1305" } local ss_rust_encrypt_method_list = { - "plain", "none", - "aes-128-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" + "plain", "none", + "aes-128-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", + "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" } local ssr_encrypt_method_list = { - "none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb", - "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", - "bf-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", - "cast5-cfb", "des-cfb", "idea-cfb", "seed-cfb", "salsa20", "chacha20", - "chacha20-ietf" + "none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb", + "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", + "bf-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", + "cast5-cfb", "des-cfb", "idea-cfb", "seed-cfb", "salsa20", "chacha20", + "chacha20-ietf" } local ssr_protocol_list = { - "origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple", - "auth_sha1", "auth_sha1_v2", "auth_sha1_v4", "auth_aes128_md5", - "auth_aes128_sha1", "auth_chain_a", "auth_chain_b", "auth_chain_c", - "auth_chain_d", "auth_chain_e", "auth_chain_f" + "origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple", + "auth_sha1", "auth_sha1_v2", "auth_sha1_v4", "auth_aes128_md5", + "auth_aes128_sha1", "auth_chain_a", "auth_chain_b", "auth_chain_c", + "auth_chain_d", "auth_chain_e", "auth_chain_f" } local ssr_obfs_list = { - "plain", "http_simple", "http_post", "random_head", "tls_simple", - "tls1.0_session_auth", "tls1.2_ticket_auth" + "plain", "http_simple", "http_post", "random_head", "tls_simple", + "tls1.0_session_auth", "tls1.2_ticket_auth" } local v_ss_encrypt_method_list = { - "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305" + "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305" } local x_ss_encrypt_method_list = { - "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" + "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" } local security_list = {"none", "auto", "aes-128-gcm", "chacha20-poly1305", "zero"} local header_type_list = { - "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" + "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" } local encrypt_methods_ss_aead = { "chacha20-ietf-poly1305", @@ -75,42 +75,42 @@ remarks.rmempty = false type = s:option(ListValue, "type", translate("Type")) if api.is_finded("ipt2socks") then - type:value("Socks", translate("Socks")) + type:value("Socks", translate("Socks")) end if api.is_finded("ss-redir") then - type:value("SS", translate("Shadowsocks Libev")) + type:value("SS", translate("Shadowsocks Libev")) end if api.is_finded("sslocal") then - type:value("SS-Rust", translate("Shadowsocks Rust")) + type:value("SS-Rust", translate("Shadowsocks Rust")) end if api.is_finded("ssr-redir") then - type:value("SSR", translate("ShadowsocksR Libev")) + type:value("SSR", translate("ShadowsocksR Libev")) end if api.is_finded("v2ray") then - type:value("V2ray", translate("V2ray")) + type:value("V2ray", translate("V2ray")) end if api.is_finded("xray") then - type:value("Xray", translate("Xray")) + type:value("Xray", translate("Xray")) end if api.is_finded("brook") then - type:value("Brook", translate("Brook")) + type:value("Brook", translate("Brook")) end --[[ if api.is_finded("trojan-plus") or api.is_finded("trojan") then - type:value("Trojan", translate("Trojan")) + type:value("Trojan", translate("Trojan")) end ]]-- if api.is_finded("trojan-plus") then - type:value("Trojan-Plus", translate("Trojan-Plus")) + type:value("Trojan-Plus", translate("Trojan-Plus")) end if api.is_finded("trojan-go") then - type:value("Trojan-Go", translate("Trojan-Go")) + type:value("Trojan-Go", translate("Trojan-Go")) end if api.is_finded("naive") then - type:value("Naiveproxy", translate("NaiveProxy")) + type:value("Naiveproxy", translate("NaiveProxy")) end if api.is_finded("hysteria") then - type:value("Hysteria", translate("Hysteria")) + type:value("Hysteria", translate("Hysteria")) end protocol = s:option(ListValue, "protocol", translate("Protocol")) @@ -133,12 +133,12 @@ iface:depends("protocol", "_iface") local nodes_table = {} for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" then - nodes_table[#nodes_table + 1] = { - id = e[".name"], - remarks = e["remark"] - } - end + if e.node_type == "normal" then + nodes_table[#nodes_table + 1] = { + id = e[".name"], + remarks = e["remark"] + } + end end -- 负载均衡列表 @@ -148,33 +148,33 @@ balancing_node:depends("protocol", "_balancing") -- 分流 uci:foreach(appname, "shunt_rules", function(e) - if e[".name"] and e.remarks then - o = s:option(ListValue, e[".name"], string.format('* %s', api.url("shunt_rules", e[".name"]), e.remarks)) - o:value("nil", translate("Close")) - o:value("_default", translate("Default")) - o:value("_direct", translate("Direct Connection")) - o:value("_blackhole", translate("Blackhole")) - o:depends("protocol", "_shunt") + if e[".name"] and e.remarks then + o = s:option(ListValue, e[".name"], string.format('* %s', api.url("shunt_rules", e[".name"]), e.remarks)) + o:value("nil", translate("Close")) + o:value("_default", translate("Default")) + o:value("_direct", translate("Direct Connection")) + o:value("_blackhole", translate("Blackhole")) + o:depends("protocol", "_shunt") - if #nodes_table > 0 then - _proxy_tag = s:option(ListValue, e[".name"] .. "_proxy_tag", string.format('* %s', e.remarks .. " " .. translate("Preproxy"))) - _proxy_tag:value("nil", translate("Close")) - _proxy_tag:value("default", translate("Default")) - _proxy_tag:value("main", translate("Default Preproxy")) - _proxy_tag.default = "nil" + if #nodes_table > 0 then + _proxy_tag = s:option(ListValue, e[".name"] .. "_proxy_tag", string.format('* %s', e.remarks .. " " .. translate("Preproxy"))) + _proxy_tag:value("nil", translate("Close")) + _proxy_tag:value("default", translate("Default")) + _proxy_tag:value("main", translate("Default Preproxy")) + _proxy_tag.default = "nil" - for k, v in pairs(nodes_table) do - o:value(v.id, v.remarks) - _proxy_tag:depends(e[".name"], v.id) - end - end - end + for k, v in pairs(nodes_table) do + o:value(v.id, v.remarks) + _proxy_tag:depends(e[".name"], v.id) + end + end + end end) shunt_tips = s:option(DummyValue, "shunt_tips", " ") shunt_tips.rawhtml = true shunt_tips.cfgvalue = function(t, n) - return string.format('%s', translate("No shunt rules? Click me to go to add.")) + return string.format('%s', translate("No shunt rules? Click me to go to add.")) end shunt_tips:depends("protocol", "_shunt") @@ -185,12 +185,12 @@ for k, v in pairs(nodes_table) do default_node:value(v.id, v.remarks) end default_node:depends("protocol", "_shunt") if #nodes_table > 0 then - o = s:option(ListValue, "main_node", string.format('* %s', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node.")) - o:value("nil", translate("Close")) - for k, v in pairs(nodes_table) do - o:value(v.id, v.remarks) - o:depends("default_node", v.id) - end + o = s:option(ListValue, "main_node", string.format('* %s', translate("Default Preproxy")), translate("When using, localhost will connect this node first and then use this node to connect the default node.")) + o:value("nil", translate("Close")) + for k, v in pairs(nodes_table) do + o:value(v.id, v.remarks) + o:depends("default_node", v.id) + end end dialerProxy = s:option(Flag, "dialerProxy", translate("dialerProxy")) @@ -504,13 +504,13 @@ uuid:depends({ type = "Xray", protocol = "vless" }) tls = s:option(Flag, "tls", translate("TLS")) tls.default = 0 tls.validate = function(self, value, t) - if value then - local type = type:formvalue(t) or "" - if value == "0" and (type == "Trojan" or type == "Trojan-Plus") then - return nil, translate("Original Trojan only supported 'tls', please choose 'tls'.") - end - return value - end + if value then + local type = type:formvalue(t) or "" + if value == "0" and (type == "Trojan" or type == "Trojan-Plus") then + return nil, translate("Original Trojan only supported 'tls', please choose 'tls'.") + end + return value + end end tls:depends({ type = "V2ray", protocol = "vmess" }) tls:depends({ type = "V2ray", protocol = "vless" }) @@ -926,11 +926,11 @@ hysteria_disable_mtu_discovery = s:option(Flag, "hysteria_disable_mtu_discovery" hysteria_disable_mtu_discovery:depends("type", "Hysteria") protocol.validate = function(self, value) - if value == "_shunt" or value == "_balancing" then - address.rmempty = true - port.rmempty = true - end - return value + if value == "_shunt" or value == "_balancing" then + address.rmempty = true + port.rmempty = true + end + return value end return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua index 76c81dd28..3ae17a53c 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_list.lua @@ -26,104 +26,104 @@ s.addremove = true s.template = "cbi/tblsection" s.extedit = api.url("node_config", "%s") function s.create(e, t) - local uuid = api.gen_uuid() - t = uuid - TypedSection.create(e, t) - luci.http.redirect(e.extedit:format(t)) + local uuid = api.gen_uuid() + t = uuid + TypedSection.create(e, t) + luci.http.redirect(e.extedit:format(t)) end function s.remove(e, t) - m.uci:foreach(appname, "socks", function(s) - if s["node"] == t then - m:del(s[".name"]) - end - end) - m.uci:foreach(appname, "haproxy_config", function(s) - if s["lbss"] and s["lbss"] == t then - m:del(s[".name"]) - end - end) - m.uci:foreach(appname, "acl_rule", function(s) - if s["tcp_node"] and s["tcp_node"] == t then - m:set(s[".name"], "tcp_node", "default") - end - if s["udp_node"] and s["udp_node"] == t then - m:set(s[".name"], "udp_node", "default") - end - end) - for k, v in ipairs(m:get("@auto_switch[0]", "tcp_node") or {}) do - if v and v == t then - sys.call(string.format("uci -q del_list %s.@auto_switch[0].tcp_node='%s'", appname, v)) - end - end - TypedSection.remove(e, t) - local new_node = "nil" - local node0 = m:get("@nodes[0]") or nil - if node0 then - new_node = node0[".name"] - end - if (m:get("@global[0]", "tcp_node") or "nil") == t then - m:set('@global[0]', "tcp_node", new_node) - end - if (m:get("@global[0]", "udp_node") or "nil") == t then - m:set('@global[0]', "udp_node", new_node) - end + m.uci:foreach(appname, "socks", function(s) + if s["node"] == t then + m:del(s[".name"]) + end + end) + m.uci:foreach(appname, "haproxy_config", function(s) + if s["lbss"] and s["lbss"] == t then + m:del(s[".name"]) + end + end) + m.uci:foreach(appname, "acl_rule", function(s) + if s["tcp_node"] and s["tcp_node"] == t then + m:set(s[".name"], "tcp_node", "default") + end + if s["udp_node"] and s["udp_node"] == t then + m:set(s[".name"], "udp_node", "default") + end + end) + for k, v in ipairs(m:get("@auto_switch[0]", "tcp_node") or {}) do + if v and v == t then + sys.call(string.format("uci -q del_list %s.@auto_switch[0].tcp_node='%s'", appname, v)) + end + end + TypedSection.remove(e, t) + local new_node = "nil" + local node0 = m:get("@nodes[0]") or nil + if node0 then + new_node = node0[".name"] + end + if (m:get("@global[0]", "tcp_node") or "nil") == t then + m:set('@global[0]', "tcp_node", new_node) + end + if (m:get("@global[0]", "udp_node") or "nil") == t then + m:set('@global[0]', "udp_node", new_node) + end end s.sortable = true -- 简洁模式 o = s:option(DummyValue, "add_from", "") o.cfgvalue = function(t, n) - local v = Value.cfgvalue(t, n) - if v and v ~= '' then - local group = m:get(n, "group") or "" - if group ~= "" then - v = v .. " " .. group - end - return v - else - return '' - end + local v = Value.cfgvalue(t, n) + if v and v ~= '' then + local group = m:get(n, "group") or "" + if group ~= "" then + v = v .. " " .. group + end + return v + else + return '' + end end o = s:option(DummyValue, "remarks", translate("Remarks")) o.rawhtml = true o.cfgvalue = function(t, n) - local str = "" - local is_sub = m:get(n, "is_sub") or "" - local group = m:get(n, "group") or "" - local remarks = m:get(n, "remarks") or "" - local type = m:get(n, "type") or "" - str = str .. string.format("", appname, n, type) - if type == "V2ray" or type == "Xray" then - local protocol = m:get(n, "protocol") - if protocol == "_balancing" then - protocol = translate("Balancing") - elseif protocol == "_shunt" then - protocol = translate("Shunt") - elseif protocol == "vmess" then - protocol = "VMess" - elseif protocol == "vless" then - protocol = "VLESS" - else - protocol = protocol:gsub("^%l",string.upper) - end - type = type .. " " .. protocol - end - local address = m:get(n, "address") or "" - local port = m:get(n, "port") or "" - str = str .. translate(type) .. ":" .. remarks - if address ~= "" and port ~= "" then - if nodes_ping:find("info") then - if datatypes.ip6addr(address) then - str = str .. string.format("([%s]:%s)", address, port) - else - str = str .. string.format("(%s:%s)", address, port) - end - end - str = str .. string.format("", appname, n, address) - str = str .. string.format("", appname, n, port) - end - return str + local str = "" + local is_sub = m:get(n, "is_sub") or "" + local group = m:get(n, "group") or "" + local remarks = m:get(n, "remarks") or "" + local type = m:get(n, "type") or "" + str = str .. string.format("", appname, n, type) + if type == "V2ray" or type == "Xray" then + local protocol = m:get(n, "protocol") + if protocol == "_balancing" then + protocol = translate("Balancing") + elseif protocol == "_shunt" then + protocol = translate("Shunt") + elseif protocol == "vmess" then + protocol = "VMess" + elseif protocol == "vless" then + protocol = "VLESS" + else + protocol = protocol:gsub("^%l",string.upper) + end + type = type .. " " .. protocol + end + local address = m:get(n, "address") or "" + local port = m:get(n, "port") or "" + str = str .. translate(type) .. ":" .. remarks + if address ~= "" and port ~= "" then + if nodes_ping:find("info") then + if datatypes.ip6addr(address) then + str = str .. string.format("([%s]:%s)", address, port) + else + str = str .. string.format("(%s:%s)", address, port) + end + end + str = str .. string.format("", appname, n, address) + str = str .. string.format("", appname, n, port) + end + return str end ---- Ping @@ -131,19 +131,19 @@ o = s:option(DummyValue, "ping") o.width = "8%" o.rawhtml = true o.cfgvalue = function(t, n) - local result = "---" - if not nodes_ping:find("auto_ping") then - result = string.format('Ping', n) - else - result = string.format('---', n) - end - return result + local result = "---" + if not nodes_ping:find("auto_ping") then + result = string.format('Ping', n) + else + result = string.format('---', n) + end + return result end o = s:option(DummyValue, "_url_test") o.rawhtml = true o.cfgvalue = function(t, n) - return string.format(' 0 then - o = s:option(ListValue, "ss_aead_type", translate("SS AEAD Node Use Type")) - for key, value in pairs(ss_aead_type) do - o:value(value, translate(value:gsub("^%l",string.upper))) - end + o = s:option(ListValue, "ss_aead_type", translate("SS AEAD Node Use Type")) + for key, value in pairs(ss_aead_type) do + o:value(value, translate(value:gsub("^%l",string.upper))) + end end if #trojan_type > 0 then - o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) - for key, value in pairs(trojan_type) do - o:value(value, translate(value:gsub("^%l",string.upper))) - end + o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) + for key, value in pairs(trojan_type) do + o:value(value, translate(value:gsub("^%l",string.upper))) + end end ---- Subscribe Delete All o = s:option(Button, "_stop", translate("Delete All Subscribe Node")) o.inputstyle = "remove" function o.write(e, e) - luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua truncate > /dev/null 2>&1") + luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua truncate > /dev/null 2>&1") end o = s:option(Button, "_update", translate("Manual subscription All")) o.inputstyle = "apply" function o.write(t, n) - luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start > /dev/null 2>&1 &") - luci.http.redirect(api.url("log")) + luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start > /dev/null 2>&1 &") + luci.http.redirect(api.url("log")) end s = m:section(TypedSection, "subscribe_list", "", "" .. translate("Please input the subscription url first, save and submit before manual subscription.") .. "") @@ -81,39 +81,39 @@ s.sortable = true s.template = "cbi/tblsection" s.extedit = api.url("node_subscribe_config", "%s") function s.create(e, t) - local id = TypedSection.create(e, t) - luci.http.redirect(e.extedit:format(id)) + local id = TypedSection.create(e, t) + luci.http.redirect(e.extedit:format(id)) end o = s:option(Value, "remark", translate("Remarks")) o.width = "auto" o.rmempty = false o.validate = function(self, value, t) - if value then - local count = 0 - m.uci:foreach(appname, "subscribe_list", function(e) - if e[".name"] ~= t and e["remark"] == value then - count = count + 1 - end - end) - if count > 0 then - return nil, translate("This remark already exists, please change a new remark.") - end - return value - end + if value then + local count = 0 + m.uci:foreach(appname, "subscribe_list", function(e) + if e[".name"] ~= t and e["remark"] == value then + count = count + 1 + end + end) + if count > 0 then + return nil, translate("This remark already exists, please change a new remark.") + end + return value + end end o = s:option(DummyValue, "_node_count") o.rawhtml = true o.cfgvalue = function(t, n) - local remark = m:get(n, "remark") or "" - local num = 0 - m.uci:foreach(appname, "nodes", function(s) - if s["add_from"] ~= "" and s["add_from"] == remark then - num = num + 1 - end - end) - return string.format("%s", remark .. " " .. translate("Node num") .. ": " .. num, num) + local remark = m:get(n, "remark") or "" + local num = 0 + m.uci:foreach(appname, "nodes", function(s) + if s["add_from"] ~= "" and s["add_from"] == remark then + num = num + 1 + end + end) + return string.format("%s", remark .. " " .. translate("Node num") .. ": " .. num, num) end o = s:option(Value, "url", translate("Subscribe URL")) @@ -123,15 +123,15 @@ o.rmempty = false o = s:option(Button, "_remove", translate("Delete the subscribed node")) o.inputstyle = "remove" function o.write(t, n) - local remark = m:get(n, "remark") or "" - luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua truncate " .. remark .. " > /dev/null 2>&1") + local remark = m:get(n, "remark") or "" + luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua truncate " .. remark .. " > /dev/null 2>&1") end o = s:option(Button, "_update", translate("Manual subscription")) o.inputstyle = "apply" function o.write(t, n) - luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start " .. n .. " > /dev/null 2>&1 &") - luci.http.redirect(api.url("log")) + luci.sys.call("lua /usr/share/" .. appname .. "/subscribe.lua start " .. n .. " > /dev/null 2>&1 &") + luci.http.redirect(api.url("log")) end return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua index 6a7625747..029259633 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua @@ -10,24 +10,24 @@ local has_trojan_go = api.is_finded("trojan-go") local ss_aead_type = {} local trojan_type = {} if has_ss then - ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev" + ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev" end if has_ss_rust then - ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" + ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" end if has_trojan_plus then - trojan_type[#trojan_type + 1] = "trojan-plus" + trojan_type[#trojan_type + 1] = "trojan-plus" end if has_v2ray then - trojan_type[#trojan_type + 1] = "v2ray" - ss_aead_type[#ss_aead_type + 1] = "v2ray" + trojan_type[#trojan_type + 1] = "v2ray" + ss_aead_type[#ss_aead_type + 1] = "v2ray" end if has_xray then - trojan_type[#trojan_type + 1] = "xray" - ss_aead_type[#ss_aead_type + 1] = "xray" + trojan_type[#trojan_type + 1] = "xray" + ss_aead_type[#ss_aead_type + 1] = "xray" end if has_trojan_go then - trojan_type[#trojan_type + 1] = "trojan-go" + trojan_type[#trojan_type + 1] = "trojan-go" end m = Map(appname) @@ -68,21 +68,21 @@ o:depends("filter_keyword_mode", "3") o:depends("filter_keyword_mode", "4") if #ss_aead_type > 0 then - o = s:option(ListValue, "ss_aead_type", translate("SS AEAD Node Use Type")) - o.default = "global" - o:value("global", translate("Use global config")) - for key, value in pairs(ss_aead_type) do - o:value(value, translate(value:gsub("^%l",string.upper))) - end + o = s:option(ListValue, "ss_aead_type", translate("SS AEAD Node Use Type")) + o.default = "global" + o:value("global", translate("Use global config")) + for key, value in pairs(ss_aead_type) do + o:value(value, translate(value:gsub("^%l",string.upper))) + end end if #trojan_type > 0 then - o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) - o.default = "global" - o:value("global", translate("Use global config")) - for key, value in pairs(trojan_type) do - o:value(value, translate(value:gsub("^%l",string.upper))) - end + o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) + o.default = "global" + o:value("global", translate("Use global config")) + for key, value in pairs(trojan_type) do + o:value(value, translate(value:gsub("^%l",string.upper))) + end end ---- Enable auto update subscribe diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua index 6e9b7be9c..2a4b195c2 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua @@ -15,7 +15,7 @@ s.addremove = false ---- Delay Start o = s:option(Value, "start_delay", translate("Delay Start"), - translate("Units:seconds")) + translate("Units:seconds")) o.default = "1" o.rmempty = true @@ -54,7 +54,7 @@ for e = 0, 23 do o:value(e, e .. translate("oclock")) end -- [[ Forwarding Settings ]]-- s = m:section(TypedSection, "global_forwarding", - translate("Forwarding Settings")) + translate("Forwarding Settings")) s.anonymous = true s.addremove = false @@ -66,9 +66,9 @@ o:value("1:65535", translate("All")) ---- UDP No Redir Ports o = s:option(Value, "udp_no_redir_ports", translate("UDP No Redir Ports"), - "" .. translate( - "Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") .. - "") + "" .. translate( + "Fill in the ports you don't want to be forwarded by the agent, with the highest priority.") .. + "") o.default = "disable" o:value("disable", translate("No patterns are used")) o:value("1:65535", translate("All")) @@ -101,36 +101,36 @@ o:value("53", "DNS") o = s:option(ListValue, "use_nft", translate("Firewall tools")) o.default = "0" if has_fw3 then - o:value("0", "IPtables") + o:value("0", "IPtables") end if has_fw4 then - o:value("1", "NFtables") + o:value("1", "NFtables") end if (os.execute("lsmod | grep -i REDIRECT >/dev/null") == 0 and os.execute("lsmod | grep -i TPROXY >/dev/null") == 0) or (os.execute("lsmod | grep -i nft_redir >/dev/null") == 0 and os.execute("lsmod | grep -i nft_tproxy >/dev/null") == 0) then - o = s:option(ListValue, "tcp_proxy_way", translate("TCP Proxy Way")) - o.default = "tproxy" - o:value("redirect", "REDIRECT") - o:value("tproxy", "TPROXY") - o:depends("ipv6_tproxy", false) + o = s:option(ListValue, "tcp_proxy_way", translate("TCP Proxy Way")) + o.default = "redirect" + o:value("redirect", "REDIRECT") + o:value("tproxy", "TPROXY") + o:depends("ipv6_tproxy", false) - o = s:option(ListValue, "_tcp_proxy_way", translate("TCP Proxy Way")) - o.default = "tproxy" - o:value("tproxy", "TPROXY") - o:depends("ipv6_tproxy", true) - o.write = function(self, section, value) - return self.map:set(section, "tcp_proxy_way", value) - end + o = s:option(ListValue, "_tcp_proxy_way", translate("TCP Proxy Way")) + o.default = "tproxy" + o:value("tproxy", "TPROXY") + o:depends("ipv6_tproxy", true) + o.write = function(self, section, value) + return self.map:set(section, "tcp_proxy_way", value) + end - if os.execute("lsmod | grep -i ip6table_mangle >/dev/null") == 0 or os.execute("lsmod | grep -i nft_tproxy >/dev/null") == 0 then - ---- IPv6 TProxy - o = s:option(Flag, "ipv6_tproxy", translate("IPv6 TProxy"), - "" .. translate( - "Experimental feature. Make sure that your node supports IPv6.") .. - "") - o.default = 0 - o.rmempty = false - end + if os.execute("lsmod | grep -i ip6table_mangle >/dev/null") == 0 or os.execute("lsmod | grep -i nft_tproxy >/dev/null") == 0 then + ---- IPv6 TProxy + o = s:option(Flag, "ipv6_tproxy", translate("IPv6 TProxy"), + "" .. translate( + "Experimental feature. Make sure that your node supports IPv6.") .. + "") + o.default = 0 + o.rmempty = false + end end o = s:option(Flag, "accept_icmp", translate("Hijacking ICMP (PING)")) @@ -141,31 +141,31 @@ o:depends("ipv6_tproxy", true) o.default = 0 if has_v2ray or has_xray then - o = s:option(Flag, "sniffing", translate("Sniffing (V2Ray/Xray)"), translate("When using the V2ray/Xray shunt, must be enabled, otherwise the shunt will invalid.")) - o.default = 1 - o.rmempty = false + o = s:option(Flag, "sniffing", translate("Sniffing (V2Ray/Xray)"), translate("When using the V2ray/Xray shunt, must be enabled, otherwise the shunt will invalid.")) + o.default = 1 + o.rmempty = false - if has_xray then - route_only = s:option(Flag, "route_only", translate("Sniffing Route Only (Xray)"), translate("When enabled, the server not will resolve the domain name again.")) - route_only.default = 0 - route_only:depends("sniffing", true) + if has_xray then + route_only = s:option(Flag, "route_only", translate("Sniffing Route Only (Xray)"), translate("When enabled, the server not will resolve the domain name again.")) + route_only.default = 0 + route_only:depends("sniffing", true) - local domains_excluded = string.format("/usr/share/%s/rules/domains_excluded", appname) - o = s:option(TextValue, "no_sniffing_hosts", translate("No Sniffing Lists"), translate("Hosts added into No Sniffing Lists will not resolve again on server (Xray only).")) - o.rows = 15 - o.wrap = "off" - 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, value) - if route_only:formvalue(section) == "0" then - fs.writefile(domains_excluded, "") - end - end - o:depends({sniffing = true, route_only = false}) + local domains_excluded = string.format("/usr/share/%s/rules/domains_excluded", appname) + o = s:option(TextValue, "no_sniffing_hosts", translate("No Sniffing Lists"), translate("Hosts added into No Sniffing Lists will not resolve again on server (Xray only).")) + o.rows = 15 + o.wrap = "off" + 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, value) + if route_only:formvalue(section) == "0" then + fs.writefile(domains_excluded, "") + end + end + o:depends({sniffing = true, route_only = false}) - o = s:option(Value, "buffer_size", translate("Buffer Size (Xray)"), translate("Buffer size for every connection (kB)")) - o.rmempty = true - o.datatype = "uinteger" - end + o = s:option(Value, "buffer_size", translate("Buffer Size (Xray)"), translate("Buffer size for every connection (kB)")) + o.rmempty = true + o.datatype = "uinteger" + end end return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua index df5ff5ca8..378f7e179 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua @@ -62,30 +62,30 @@ o.default = 0 o:depends("auto_update", true) if has_v2ray or has_xray then - o = s:option(Value, "v2ray_location_asset", translate("Location of V2ray/Xray asset"), translate("This variable specifies a directory where geoip.dat and geosite.dat files are.")) - o.default = "/usr/share/v2ray/" - o.rmempty = false - - s = m:section(TypedSection, "shunt_rules", "V2ray/Xray " .. translate("Shunt Rule"), "" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "") - s.template = "cbi/tblsection" - s.anonymous = false - s.addremove = true - s.sortable = true - s.extedit = api.url("shunt_rules", "%s") - function s.create(e, t) - TypedSection.create(e, t) - luci.http.redirect(e.extedit:format(t)) - end - function s.remove(e, t) - m.uci:foreach(appname, "nodes", function(s) - if s["protocol"] and s["protocol"] == "_shunt" then - m:del(s[".name"], t) - end - end) - TypedSection.remove(e, t) - end + o = s:option(Value, "v2ray_location_asset", translate("Location of V2ray/Xray asset"), translate("This variable specifies a directory where geoip.dat and geosite.dat files are.")) + o.default = "/usr/share/v2ray/" + o.rmempty = false - o = s:option(DummyValue, "remarks", translate("Remarks")) + s = m:section(TypedSection, "shunt_rules", "V2ray/Xray " .. translate("Shunt Rule"), "" .. translate("Please note attention to the priority, the higher the order, the higher the priority.") .. "") + s.template = "cbi/tblsection" + s.anonymous = false + s.addremove = true + s.sortable = true + s.extedit = api.url("shunt_rules", "%s") + function s.create(e, t) + TypedSection.create(e, t) + luci.http.redirect(e.extedit:format(t)) + end + function s.remove(e, t) + m.uci:foreach(appname, "nodes", function(s) + if s["protocol"] and s["protocol"] == "_shunt" then + m:del(s[".name"], t) + end + end) + TypedSection.remove(e, t) + end + + o = s:option(DummyValue, "remarks", translate("Remarks")) end return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua index 1e4753d68..2ac0f2314 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/rule_list.lua @@ -24,28 +24,28 @@ o = s:taboption("direct_list", TextValue, "direct_host", "", " o.rows = 15 o.wrap = "off" o.cfgvalue = function(self, section) - return fs.readfile(direct_host) or "" + return fs.readfile(direct_host) or "" end o.write = function(self, section, value) - fs.writefile(direct_host, value:gsub("\r\n", "\n")) - sys.call("rm -rf /tmp/etc/passwall_tmp/dns_*") + fs.writefile(direct_host, value:gsub("\r\n", "\n")) + sys.call("rm -rf /tmp/etc/passwall_tmp/dns_*") end o.remove = function(self, section, value) - fs.writefile(direct_host, "") - sys.call("rm -rf /tmp/etc/passwall_tmp/dns_*") + fs.writefile(direct_host, "") + sys.call("rm -rf /tmp/etc/passwall_tmp/dns_*") end o.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - if host:find("#") and host:find("#") == 1 then - return value - end - if not datatypes.hostname(host) then - return nil, host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - return value + local hosts= {} + string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) + for index, host in ipairs(hosts) do + if host:find("#") and host:find("#") == 1 then + return value + end + if not datatypes.hostname(host) then + return nil, host .. " " .. translate("Not valid domain name, please re-enter!") + end + end + return value end ---- Direct IP @@ -54,26 +54,26 @@ o = s:taboption("direct_list", TextValue, "direct_ip", "", "" o.rows = 15 o.wrap = "off" o.cfgvalue = function(self, section) - return fs.readfile(direct_ip) or "" + return fs.readfile(direct_ip) or "" end o.write = function(self, section, value) - fs.writefile(direct_ip, value:gsub("\r\n", "\n")) + fs.writefile(direct_ip, value:gsub("\r\n", "\n")) end o.remove = function(self, section, value) - fs.writefile(direct_ip, "") + fs.writefile(direct_ip, "") end o.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if ipmask:find("#") and ipmask:find("#") == 1 then - return value - end - if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value + local ipmasks= {} + string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) + for index, ipmask in ipairs(ipmasks) do + if ipmask:find("#") and ipmask:find("#") == 1 then + return value + end + if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then + return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") + end + end + return value end ---- Proxy Hosts @@ -82,28 +82,28 @@ o = s:taboption("proxy_list", TextValue, "proxy_host", "", "" o.rows = 15 o.wrap = "off" o.cfgvalue = function(self, section) - return fs.readfile(proxy_host) or "" + return fs.readfile(proxy_host) or "" end o.write = function(self, section, value) - fs.writefile(proxy_host, value:gsub("\r\n", "\n")) - sys.call("rm -rf /tmp/etc/passwall_tmp/dns_*") + fs.writefile(proxy_host, value:gsub("\r\n", "\n")) + sys.call("rm -rf /tmp/etc/passwall_tmp/dns_*") end o.remove = function(self, section, value) - fs.writefile(proxy_host, "") - sys.call("rm -rf /tmp/etc/passwall_tmp/dns_*") + fs.writefile(proxy_host, "") + sys.call("rm -rf /tmp/etc/passwall_tmp/dns_*") end o.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - if host:find("#") and host:find("#") == 1 then - return value - end - if not datatypes.hostname(host) then - return nil, host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - return value + local hosts= {} + string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) + for index, host in ipairs(hosts) do + if host:find("#") and host:find("#") == 1 then + return value + end + if not datatypes.hostname(host) then + return nil, host .. " " .. translate("Not valid domain name, please re-enter!") + end + end + return value end ---- Proxy IP @@ -112,26 +112,26 @@ o = s:taboption("proxy_list", TextValue, "proxy_ip", "", "" .. o.rows = 15 o.wrap = "off" o.cfgvalue = function(self, section) - return fs.readfile(proxy_ip) or "" + return fs.readfile(proxy_ip) or "" end o.write = function(self, section, value) - fs.writefile(proxy_ip, value:gsub("\r\n", "\n")) + fs.writefile(proxy_ip, value:gsub("\r\n", "\n")) end o.remove = function(self, section, value) - fs.writefile(proxy_ip, "") + fs.writefile(proxy_ip, "") end o.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if ipmask:find("#") and ipmask:find("#") == 1 then - return value - end - if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value + local ipmasks= {} + string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) + for index, ipmask in ipairs(ipmasks) do + if ipmask:find("#") and ipmask:find("#") == 1 then + return value + end + if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then + return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") + end + end + return value end ---- Block Hosts @@ -140,26 +140,26 @@ o = s:taboption("block_list", TextValue, "block_host", "", "" o.rows = 15 o.wrap = "off" o.cfgvalue = function(self, section) - return fs.readfile(block_host) or "" + return fs.readfile(block_host) or "" end o.write = function(self, section, value) - fs.writefile(block_host, value:gsub("\r\n", "\n")) + fs.writefile(block_host, value:gsub("\r\n", "\n")) end o.remove = function(self, section, value) - fs.writefile(block_host, "") + fs.writefile(block_host, "") end o.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - if host:find("#") and host:find("#") == 1 then - return value - end - if not datatypes.hostname(host) then - return nil, host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - return value + local hosts= {} + string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) + for index, host in ipairs(hosts) do + if host:find("#") and host:find("#") == 1 then + return value + end + if not datatypes.hostname(host) then + return nil, host .. " " .. translate("Not valid domain name, please re-enter!") + end + end + return value end ---- Block IP @@ -168,26 +168,26 @@ o = s:taboption("block_list", TextValue, "block_ip", "", "" .. o.rows = 15 o.wrap = "off" o.cfgvalue = function(self, section) - return fs.readfile(block_ip) or "" + return fs.readfile(block_ip) or "" end o.write = function(self, section, value) - fs.writefile(block_ip, value:gsub("\r\n", "\n")) + fs.writefile(block_ip, value:gsub("\r\n", "\n")) end o.remove = function(self, section, value) - fs.writefile(block_ip, "") + fs.writefile(block_ip, "") end o.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if ipmask:find("#") and ipmask:find("#") == 1 then - return value - end - if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - return value + local ipmasks= {} + string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) + for index, ipmask in ipairs(ipmasks) do + if ipmask:find("#") and ipmask:find("#") == 1 then + return value + end + if not ( datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask) ) then + return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") + end + end + return value end ---- Lan IPv4 @@ -196,26 +196,26 @@ o = s:taboption("lan_ip_list", TextValue, "lanlist_ipv4", "", "" .. t o.rows = 15 o.wrap = "off" o.cfgvalue = function(self, section) - return fs.readfile(hosts) or "" + return fs.readfile(hosts) or "" end o.write = function(self, section, value) - fs.writefile(hosts, value:gsub("\r\n", "\n")) + fs.writefile(hosts, value:gsub("\r\n", "\n")) end o.remove = function(self, section, value) - fs.writefile(hosts, "") + fs.writefile(hosts, "") end return m diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua index 6eae2cdbe..1e457b8e0 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua @@ -22,29 +22,29 @@ domain_list = s:option(TextValue, "domain_list", translate("Domain")) domain_list.rows = 10 domain_list.wrap = "off" domain_list.validate = function(self, value) - local hosts= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) - for index, host in ipairs(hosts) do - local flag = 1 - local tmp_host = host - if host:find("regexp:") and host:find("regexp:") == 1 then - flag = 0 - elseif host:find("domain:.") and host:find("domain:.") == 1 then - tmp_host = host:gsub("domain:", "") - elseif host:find("full:.") and host:find("full:.") == 1 then - tmp_host = host:gsub("full:", "") - elseif host:find("geosite:") and host:find("geosite:") == 1 then - flag = 0 - elseif host:find("ext:") and host:find("ext:") == 1 then - flag = 0 - end - if flag == 1 then - if not datatypes.hostname(tmp_host) then - return nil, tmp_host .. " " .. translate("Not valid domain name, please re-enter!") - end - end - end - return value + local hosts= {} + string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(hosts, w) end) + for index, host in ipairs(hosts) do + local flag = 1 + local tmp_host = host + if host:find("regexp:") and host:find("regexp:") == 1 then + flag = 0 + elseif host:find("domain:.") and host:find("domain:.") == 1 then + tmp_host = host:gsub("domain:", "") + elseif host:find("full:.") and host:find("full:.") == 1 then + tmp_host = host:gsub("full:", "") + elseif host:find("geosite:") and host:find("geosite:") == 1 then + flag = 0 + elseif host:find("ext:") and host:find("ext:") == 1 then + flag = 0 + end + if flag == 1 then + if not datatypes.hostname(tmp_host) then + return nil, tmp_host .. " " .. translate("Not valid domain name, please re-enter!") + end + end + end + return value end domain_list.description = "
  • " .. translate("Plaintext: If this string matches any part of the targeting domain, this rule takes effet. Example: rule 'sina.com' matches targeting domain 'sina.com', 'sina.com.cn' and 'www.sina.com', but not 'sina.cn'.") .. "
  • " .. translate("Regular expression: Begining with 'regexp:', the rest is a regular expression. When the regexp matches targeting domain, this rule takes effect. Example: rule 'regexp:\\.goo.*\\.com$' matches 'www.google.com' and 'fonts.googleapis.com', but not 'google.com'.") @@ -57,18 +57,18 @@ ip_list = s:option(TextValue, "ip_list", "IP") ip_list.rows = 10 ip_list.wrap = "off" ip_list.validate = function(self, value) - local ipmasks= {} - string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) - for index, ipmask in ipairs(ipmasks) do - if ipmask:find("geoip:") and ipmask:find("geoip:") == 1 then - elseif ipmask:find("ext:") and ipmask:find("ext:") == 1 then - else - if not (datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask)) then - return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") - end - end - end - return value + local ipmasks= {} + string.gsub(value, '[^' .. "\r\n" .. ']+', function(w) table.insert(ipmasks, w) end) + for index, ipmask in ipairs(ipmasks) do + if ipmask:find("geoip:") and ipmask:find("geoip:") == 1 then + elseif ipmask:find("ext:") and ipmask:find("ext:") == 1 then + else + if not (datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask)) then + return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") + end + end + end + return value end ip_list.description = "
    • " .. translate("IP: such as '127.0.0.1'.") .. "
    • " .. translate("CIDR: such as '127.0.0.0/8'.") diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua index 22a26f216..a8e31454a 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/index.lua @@ -16,15 +16,15 @@ t.sortable = true t.template = "cbi/tblsection" t.extedit = api.url("server_user", "%s") function t.create(e, t) - local uuid = api.gen_uuid() - t = uuid - TypedSection.create(e, t) - luci.http.redirect(e.extedit:format(t)) + local uuid = api.gen_uuid() + t = uuid + TypedSection.create(e, t) + luci.http.redirect(e.extedit:format(t)) end function t.remove(e, t) - e.map.proceed = true - e.map:del(t) - luci.http.redirect(api.url("server")) + e.map.proceed = true + e.map:del(t) + luci.http.redirect(api.url("server")) end e = t:option(Flag, "enable", translate("Enable")) @@ -34,7 +34,7 @@ e.rmempty = false e = t:option(DummyValue, "status", translate("Status")) e.rawhtml = true e.cfgvalue = function(t, n) - return string.format('%s', translate("Collecting data...")) + return string.format('%s', translate("Collecting data...")) end e = t:option(DummyValue, "remarks", translate("Remarks")) @@ -43,21 +43,21 @@ e.width = "15%" ---- Type e = t:option(DummyValue, "type", translate("Type")) e.cfgvalue = function(t, n) - local v = Value.cfgvalue(t, n) - if v then - if v == "V2ray" or v == "Xray" then - local protocol = m:get(n, "protocol") - if protocol == "vmess" then - protocol = "VMess" - elseif protocol == "vless" then - protocol = "VLESS" - else - protocol = protocol:gsub("^%l",string.upper) - end - return v .. " -> " .. protocol - end - return v - end + local v = Value.cfgvalue(t, n) + if v then + if v == "V2ray" or v == "Xray" then + local protocol = m:get(n, "protocol") + if protocol == "vmess" then + protocol = "VMess" + elseif protocol == "vless" then + protocol = "VLESS" + else + protocol = protocol:gsub("^%l",string.upper) + end + return v .. " -> " .. protocol + end + return v + end end e = t:option(DummyValue, "port", translate("Port")) @@ -70,4 +70,3 @@ m:append(Template("passwall/server/log")) m:append(Template("passwall/server/users_list_status")) return m - 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 023d7efcd..f66cb5e43 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/user.lua @@ -1,49 +1,49 @@ local api = require "luci.passwall.api" local ss_encrypt_method_list = { - "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", - "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", - "camellia-192-cfb", "camellia-256-cfb", "salsa20", "chacha20", - "chacha20-ietf", -- aead - "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305" + "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", + "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", + "camellia-192-cfb", "camellia-256-cfb", "salsa20", "chacha20", + "chacha20-ietf", -- aead + "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", + "xchacha20-ietf-poly1305" } local ss_rust_encrypt_method_list = { - "plain", "none", - "aes-128-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" + "plain", "none", + "aes-128-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", + "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" } local ssr_encrypt_method_list = { - "none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb", - "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", - "bf-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", - "cast5-cfb", "des-cfb", "idea-cfb", "seed-cfb", "salsa20", "chacha20", - "chacha20-ietf" + "none", "table", "rc2-cfb", "rc4", "rc4-md5", "rc4-md5-6", "aes-128-cfb", + "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", "aes-192-ctr", "aes-256-ctr", + "bf-cfb", "camellia-128-cfb", "camellia-192-cfb", "camellia-256-cfb", + "cast5-cfb", "des-cfb", "idea-cfb", "seed-cfb", "salsa20", "chacha20", + "chacha20-ietf" } local ssr_protocol_list = { - "origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple", - "auth_sha1", "auth_sha1_v2", "auth_sha1_v4", "auth_aes128_md5", - "auth_aes128_sha1", "auth_chain_a", "auth_chain_b", "auth_chain_c", - "auth_chain_d", "auth_chain_e", "auth_chain_f" + "origin", "verify_simple", "verify_deflate", "verify_sha1", "auth_simple", + "auth_sha1", "auth_sha1_v2", "auth_sha1_v4", "auth_aes128_md5", + "auth_aes128_sha1", "auth_chain_a", "auth_chain_b", "auth_chain_c", + "auth_chain_d", "auth_chain_e", "auth_chain_f" } local ssr_obfs_list = { - "plain", "http_simple", "http_post", "random_head", "tls_simple", - "tls1.0_session_auth", "tls1.2_ticket_auth" + "plain", "http_simple", "http_post", "random_head", "tls_simple", + "tls1.0_session_auth", "tls1.2_ticket_auth" } local v_ss_encrypt_method_list = { - "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305" + "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305" } local x_ss_encrypt_method_list = { - "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" + "aes-128-gcm", "aes-256-gcm", "chacha20-poly1305", "xchacha20-poly1305", "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" } local header_type_list = { - "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" + "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" } local encrypt_methods_ss_aead = { @@ -69,39 +69,39 @@ remarks.rmempty = false type = s:option(ListValue, "type", translate("Type")) if api.is_finded("microsocks") then - type:value("Socks", translate("Socks")) + type:value("Socks", translate("Socks")) end if api.is_finded("ss-server") then - type:value("SS", translate("Shadowsocks")) + type:value("SS", translate("Shadowsocks")) end if api.is_finded("ssserver") then - type:value("SS-Rust", translate("Shadowsocks Rust")) + type:value("SS-Rust", translate("Shadowsocks Rust")) end if api.is_finded("ssr-server") then - type:value("SSR", translate("ShadowsocksR")) + type:value("SSR", translate("ShadowsocksR")) end if api.is_finded("v2ray") then - type:value("V2ray", translate("V2ray")) + type:value("V2ray", translate("V2ray")) end if api.is_finded("xray") then - type:value("Xray", translate("Xray")) + type:value("Xray", translate("Xray")) end if api.is_finded("brook") then - type:value("Brook", translate("Brook")) + type:value("Brook", translate("Brook")) end --[[ if api.is_finded("trojan-plus") or api.is_finded("trojan") then - type:value("Trojan", translate("Trojan")) + type:value("Trojan", translate("Trojan")) end ]]-- if api.is_finded("trojan-plus") then - type:value("Trojan-Plus", translate("Trojan-Plus")) + type:value("Trojan-Plus", translate("Trojan-Plus")) end if api.is_finded("trojan-go") then - type:value("Trojan-Go", translate("Trojan-Go")) + type:value("Trojan-Go", translate("Trojan-Go")) end if api.is_finded("hysteria") then - type:value("Hysteria", translate("Hysteria")) + type:value("Hysteria", translate("Hysteria")) end protocol = s:option(ListValue, "protocol", translate("Protocol")) @@ -137,14 +137,14 @@ port.rmempty = false auth = s:option(Flag, "auth", translate("Auth")) auth.validate = function(self, value, t) - if value and value == "1" then - local user_v = username:formvalue(t) or "" - local pass_v = password:formvalue(t) or "" - if user_v == "" or pass_v == "" then - return nil, translate("Username and Password must be used together!") - end - end - return value + if value and value == "1" then + local user_v = username:formvalue(t) or "" + local pass_v = password:formvalue(t) or "" + if user_v == "" or pass_v == "" then + return nil, translate("Username and Password must be used together!") + end + end + return value end auth:depends("type", "Socks") auth:depends({ type = "V2ray", protocol = "socks" }) @@ -343,7 +343,7 @@ udp_forward:depends({ type = "Xray", protocol = "socks" }) uuid = s:option(DynamicList, "uuid", translate("ID") .. "/" .. translate("Password")) for i = 1, 3 do - uuid:value(api.gen_uuid(1)) + uuid:value(api.gen_uuid(1)) end uuid:depends({ type = "V2ray", protocol = "vmess" }) uuid:depends({ type = "V2ray", protocol = "vless" }) @@ -358,20 +358,20 @@ uuid:depends("type", "Trojan-Plus") tls = s:option(Flag, "tls", translate("TLS")) tls.default = 0 tls.validate = function(self, value, t) - if value then - local type = type:formvalue(t) or "" - if value == "0" and (type == "Trojan" or type == "Trojan-Plus") then - return nil, translate("Original Trojan only supported 'tls', please choose 'tls'.") - end - if value == "1" then - local ca = tls_certificateFile:formvalue(t) or "" - local key = tls_keyFile:formvalue(t) or "" - if ca == "" or key == "" then - return nil, translate("Public key and Private key path can not be empty!") - end - end - return value - end + if value then + local type = type:formvalue(t) or "" + if value == "0" and (type == "Trojan" or type == "Trojan-Plus") then + return nil, translate("Original Trojan only supported 'tls', please choose 'tls'.") + end + if value == "1" then + local ca = tls_certificateFile:formvalue(t) or "" + local key = tls_keyFile:formvalue(t) or "" + if ca == "" or key == "" then + return nil, translate("Public key and Private key path can not be empty!") + end + end + return value + end end tls:depends({ type = "V2ray", protocol = "vmess" }) tls:depends({ type = "V2ray", protocol = "vless" }) @@ -411,14 +411,14 @@ alpn:depends({ type = "Xray", tls = true }) tls_certificateFile = s:option(FileUpload, "tls_certificateFile", translate("Public key absolute path"), translate("as:") .. "/etc/ssl/fullchain.pem") tls_certificateFile.validate = function(self, value, t) - if value and value ~= "" then - if not nixio.fs.access(value) then - return nil, translate("Can't find this file!") - else - return value - end - end - return nil + if value and value ~= "" then + if not nixio.fs.access(value) then + return nil, translate("Can't find this file!") + else + return value + end + end + return nil end tls_certificateFile.default = "/etc/config/ssl/" .. arg[1] .. ".pem" tls_certificateFile:depends("tls", true) @@ -426,14 +426,14 @@ tls_certificateFile:depends("type", "Hysteria") tls_keyFile = s:option(FileUpload, "tls_keyFile", translate("Private key absolute path"), translate("as:") .. "/etc/ssl/private.key") tls_keyFile.validate = function(self, value, t) - if value and value ~= "" then - if not nixio.fs.access(value) then - return nil, translate("Can't find this file!") - else - return value - end - end - return nil + if value and value ~= "" then + if not nixio.fs.access(value) then + return nil, translate("Can't find this file!") + else + return value + end + end + return nil end tls_keyFile.default = "/etc/config/ssl/" .. arg[1] .. ".key" tls_keyFile:depends("tls", true) @@ -673,12 +673,12 @@ accept_lan:depends("type", "Xray") local nodes_table = {} for k, e in ipairs(api.get_valid_nodes()) do - if e.node_type == "normal" and (e.type == "V2ray" or e.type == "Xray") then - nodes_table[#nodes_table + 1] = { - id = e[".name"], - remarks = e["remark"] - } - end + if e.node_type == "normal" and (e.type == "V2ray" or e.type == "Xray") then + nodes_table[#nodes_table + 1] = { + id = e[".name"], + remarks = e["remark"] + } + end end outbound_node = s:option(ListValue, "outbound_node", translate("outbound node")) diff --git a/luci-app-passwall/luasrc/passwall/api.lua b/luci-app-passwall/luasrc/passwall/api.lua index 4644aeef9..0534c2599 100644 --- a/luci-app-passwall/luasrc/passwall/api.lua +++ b/luci-app-passwall/luasrc/passwall/api.lua @@ -18,816 +18,816 @@ LOG_FILE = "/tmp/log/" .. appname .. ".log" CACHE_PATH = "/tmp/etc/" .. appname .. "_tmp" function exec_call(cmd) - local process = io.popen(cmd .. '; echo -e "\n$?"') - local lines = {} - local result = "" - local return_code - for line in process:lines() do - lines[#lines + 1] = line - end - process:close() - if #lines > 0 then - return_code = lines[#lines] - for i = 1, #lines - 1 do - result = result .. lines[i] .. ((i == #lines - 1) and "" or "\n") - end - end - return tonumber(return_code), trim(result) + local process = io.popen(cmd .. '; echo -e "\n$?"') + local lines = {} + local result = "" + local return_code + for line in process:lines() do + lines[#lines + 1] = line + end + process:close() + if #lines > 0 then + return_code = lines[#lines] + for i = 1, #lines - 1 do + result = result .. lines[i] .. ((i == #lines - 1) and "" or "\n") + end + end + return tonumber(return_code), trim(result) end function base64Decode(text) - local raw = text - if not text then return '' end - text = text:gsub("%z", "") - text = text:gsub("%c", "") - text = text:gsub("_", "/") - text = text:gsub("-", "+") - local mod4 = #text % 4 - text = text .. string.sub('====', mod4 + 1) - local result = nixio.bin.b64decode(text) - if result then - return result:gsub("%z", "") - else - return raw - end + local raw = text + if not text then return '' end + text = text:gsub("%z", "") + text = text:gsub("%c", "") + text = text:gsub("_", "/") + text = text:gsub("-", "+") + local mod4 = #text % 4 + text = text .. string.sub('====', mod4 + 1) + local result = nixio.bin.b64decode(text) + if result then + return result:gsub("%z", "") + else + return raw + end end function curl_base(url, file, args) - if not args then args = {} end - if file then - args[#args + 1] = "-o " .. file - end - local cmd = string.format('curl %s "%s"', table_join(args), url) - return exec_call(cmd) + if not args then args = {} end + if file then + args[#args + 1] = "-o " .. file + end + local cmd = string.format('curl %s "%s"', table_join(args), url) + return exec_call(cmd) end function curl_proxy(url, file, args) - --使用代理 - local socks_server = luci.sys.exec("[ -f /tmp/etc/passwall/TCP_SOCKS_server ] && echo -n $(cat /tmp/etc/passwall/TCP_SOCKS_server) || echo -n ''") - if socks_server ~= "" then - if not args then args = {} end - local tmp_args = clone(args) - tmp_args[#tmp_args + 1] = "-x socks5h://" .. socks_server - return curl_base(url, file, tmp_args) - end - return nil, nil + --使用代理 + local socks_server = luci.sys.exec("[ -f /tmp/etc/passwall/TCP_SOCKS_server ] && echo -n $(cat /tmp/etc/passwall/TCP_SOCKS_server) || echo -n ''") + if socks_server ~= "" then + if not args then args = {} end + local tmp_args = clone(args) + tmp_args[#tmp_args + 1] = "-x socks5h://" .. socks_server + return curl_base(url, file, tmp_args) + end + return nil, nil end function curl_logic(url, file, args) - local return_code, result = curl_proxy(url, file, args) - if not return_code or return_code ~= 0 then - return_code, result = curl_base(url, file, args) - end - return return_code, result + local return_code, result = curl_proxy(url, file, args) + if not return_code or return_code ~= 0 then + return_code, result = curl_base(url, file, args) + end + return return_code, result end function url(...) - local url = string.format("admin/services/%s", appname) - local args = { ... } - for i, v in pairs(args) do - if v ~= "" then - url = url .. "/" .. v - end - end - return require "luci.dispatcher".build_url(url) + local url = string.format("admin/services/%s", appname) + local args = { ... } + for i, v in pairs(args) do + if v ~= "" then + url = url .. "/" .. v + end + end + return require "luci.dispatcher".build_url(url) end function trim(s) - return (s:gsub("^%s*(.-)%s*$", "%1")) + return (s:gsub("^%s*(.-)%s*$", "%1")) end function is_exist(table, value) - for index, k in ipairs(table) do - if k == value then - return true - end - end - return false + for index, k in ipairs(table) do + if k == value then + return true + end + end + return false end function repeat_exist(table, value) - local count = 0 - for index, k in ipairs(table) do - if k:find("-") and k == value then - count = count + 1 - end - end - if count > 1 then - return true - end - return false + local count = 0 + for index, k in ipairs(table) do + if k:find("-") and k == value then + count = count + 1 + end + end + if count > 1 then + return true + end + return false end function remove(...) - for index, value in ipairs({...}) do - if value and #value > 0 and value ~= "/" then - sys.call(string.format("rm -rf %s", value)) - end - end + for index, value in ipairs({...}) do + if value and #value > 0 and value ~= "/" then + sys.call(string.format("rm -rf %s", value)) + end + end end function is_install(package) - if package and #package > 0 then - return sys.call(string.format('opkg list-installed | grep "%s" > /dev/null 2>&1', package)) == 0 - end - return false + if package and #package > 0 then + return sys.call(string.format('opkg list-installed | grep "%s" > /dev/null 2>&1', package)) == 0 + end + return false end function get_args(arg) - local var = {} - for i, arg_k in pairs(arg) do - if i > 0 then - local v = arg[i + 1] - if v then - if repeat_exist(arg, v) == false then - var[arg_k] = v - end - end - end - end - return var + local var = {} + for i, arg_k in pairs(arg) do + if i > 0 then + local v = arg[i + 1] + if v then + if repeat_exist(arg, v) == false then + var[arg_k] = v + end + end + end + end + return var end function get_function_args(arg) - local var = nil - if arg and #arg > 1 then - local param = {} - for i = 2, #arg do - param[#param + 1] = arg[i] - end - var = get_args(param) - end - return var + local var = nil + if arg and #arg > 1 then + local param = {} + for i = 2, #arg do + param[#param + 1] = arg[i] + end + var = get_args(param) + end + return var end function strToTable(str) - if str == nil or type(str) ~= "string" then - return {} - end + if str == nil or type(str) ~= "string" then + return {} + end - return loadstring("return " .. str)() + return loadstring("return " .. str)() end function is_normal_node(e) - if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then - return false - end - return true + if e and e.type and e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then + return false + end + return true end function is_special_node(e) - return is_normal_node(e) == false + return is_normal_node(e) == false end function is_ip(val) - if is_ipv6(val) then - val = get_ipv6_only(val) - end - return datatypes.ipaddr(val) + if is_ipv6(val) then + val = get_ipv6_only(val) + end + return datatypes.ipaddr(val) end function is_ipv6(val) - local str = val - local address = val:match('%[(.*)%]') - if address then - str = address - end - if datatypes.ip6addr(str) then - return true - end - return false + local str = val + local address = val:match('%[(.*)%]') + if address then + str = address + end + if datatypes.ip6addr(str) then + return true + end + return false end function is_ipv6addrport(val) - if is_ipv6(val) then - local address, port = val:match('%[(.*)%]:([^:]+)$') - if port then - return datatypes.port(port) - end - end - return false + if is_ipv6(val) then + local address, port = val:match('%[(.*)%]:([^:]+)$') + if port then + return datatypes.port(port) + end + end + return false end function get_ipv6_only(val) - local result = "" - if is_ipv6(val) then - result = val - if val:match('%[(.*)%]') then - result = val:match('%[(.*)%]') - end - end - return result + local result = "" + if is_ipv6(val) then + result = val + if val:match('%[(.*)%]') then + result = val:match('%[(.*)%]') + end + end + return result end function get_ipv6_full(val) - local result = "" - if is_ipv6(val) then - result = val - if not val:match('%[(.*)%]') then - result = "[" .. result .. "]" - end - end - return result + local result = "" + if is_ipv6(val) then + result = val + if not val:match('%[(.*)%]') then + result = "[" .. result .. "]" + end + end + return result end function get_ip_type(val) - if is_ipv6(val) then - return "6" - elseif datatypes.ip4addr(val) then - return "4" - end - return "" + if is_ipv6(val) then + return "6" + elseif datatypes.ip4addr(val) then + return "4" + end + return "" end function is_mac(val) - return datatypes.macaddr(val) + return datatypes.macaddr(val) end function ip_or_mac(val) - if val then - if get_ip_type(val) == "4" then - return "ip" - end - if is_mac(val) then - return "mac" - end - end - return "" + if val then + if get_ip_type(val) == "4" then + return "ip" + end + if is_mac(val) then + return "mac" + end + end + return "" end function iprange(val) - if val then - local ipStart, ipEnd = val:match("^([^/]+)-([^/]+)$") - if (ipStart and datatypes.ip4addr(ipStart)) and (ipEnd and datatypes.ip4addr(ipEnd)) then - return true - end - end - return false + if val then + local ipStart, ipEnd = val:match("^([^/]+)-([^/]+)$") + if (ipStart and datatypes.ip4addr(ipStart)) and (ipEnd and datatypes.ip4addr(ipEnd)) then + return true + end + end + return false end function get_domain_from_url(url) - local domain = string.match(url, "//([^/]+)") - if domain then - return domain - end - return url + local domain = string.match(url, "//([^/]+)") + if domain then + return domain + end + return url end function get_valid_nodes() - local nodes_ping = uci_get_type("global_other", "nodes_ping") or "" - local nodes = {} - uci:foreach(appname, "nodes", function(e) - e.id = e[".name"] - if e.type and e.remarks then - if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then - e["remark"] = "%s:[%s] " % {i18n.translatef(e.type .. e.protocol), e.remarks} - e["node_type"] = "special" - nodes[#nodes + 1] = e - end - if e.port and e.address then - local address = e.address - if is_ip(address) or datatypes.hostname(address) then - local type = e.type - if (type == "V2ray" or type == "Xray") and e.protocol then - local protocol = e.protocol - if protocol == "vmess" then - protocol = "VMess" - elseif protocol == "vless" then - protocol = "VLESS" - else - protocol = protocol:gsub("^%l",string.upper) - end - type = type .. " " .. protocol - end - if is_ipv6(address) then address = get_ipv6_full(address) end - e["remark"] = "%s:[%s]" % {type, e.remarks} - if nodes_ping:find("info") then - e["remark"] = "%s:[%s] %s:%s" % {type, e.remarks, address, e.port} - end - e.node_type = "normal" - nodes[#nodes + 1] = e - end - end - end - end) - return nodes + local nodes_ping = uci_get_type("global_other", "nodes_ping") or "" + local nodes = {} + uci:foreach(appname, "nodes", function(e) + e.id = e[".name"] + if e.type and e.remarks then + if e.protocol and (e.protocol == "_balancing" or e.protocol == "_shunt" or e.protocol == "_iface") then + e["remark"] = "%s:[%s] " % {i18n.translatef(e.type .. e.protocol), e.remarks} + e["node_type"] = "special" + nodes[#nodes + 1] = e + end + if e.port and e.address then + local address = e.address + if is_ip(address) or datatypes.hostname(address) then + local type = e.type + if (type == "V2ray" or type == "Xray") and e.protocol then + local protocol = e.protocol + if protocol == "vmess" then + protocol = "VMess" + elseif protocol == "vless" then + protocol = "VLESS" + else + protocol = protocol:gsub("^%l",string.upper) + end + type = type .. " " .. protocol + end + if is_ipv6(address) then address = get_ipv6_full(address) end + e["remark"] = "%s:[%s]" % {type, e.remarks} + if nodes_ping:find("info") then + e["remark"] = "%s:[%s] %s:%s" % {type, e.remarks, address, e.port} + end + e.node_type = "normal" + nodes[#nodes + 1] = e + end + end + end + end) + return nodes end function get_full_node_remarks(n) - local remarks = "" - if n then - if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt" or n.protocol == "_iface") then - remarks = "%s:[%s] " % {i18n.translatef(n.type .. n.protocol), n.remarks} - else - local type2 = n.type - if (n.type == "V2ray" or n.type == "Xray") and n.protocol then - local protocol = n.protocol - if protocol == "vmess" then - protocol = "VMess" - elseif protocol == "vless" then - protocol = "VLESS" - else - protocol = protocol:gsub("^%l",string.upper) - end - type2 = type2 .. " " .. protocol - end - remarks = "%s:[%s] %s:%s" % {type2, n.remarks, n.address, n.port} - end - end - return remarks + local remarks = "" + if n then + if n.protocol and (n.protocol == "_balancing" or n.protocol == "_shunt" or n.protocol == "_iface") then + remarks = "%s:[%s] " % {i18n.translatef(n.type .. n.protocol), n.remarks} + else + local type2 = n.type + if (n.type == "V2ray" or n.type == "Xray") and n.protocol then + local protocol = n.protocol + if protocol == "vmess" then + protocol = "VMess" + elseif protocol == "vless" then + protocol = "VLESS" + else + protocol = protocol:gsub("^%l",string.upper) + end + type2 = type2 .. " " .. protocol + end + remarks = "%s:[%s] %s:%s" % {type2, n.remarks, n.address, n.port} + end + end + return remarks end function gen_uuid(format) - local uuid = sys.exec("echo -n $(cat /proc/sys/kernel/random/uuid)") - if format == nil then - uuid = string.gsub(uuid, "-", "") - end - return uuid + local uuid = sys.exec("echo -n $(cat /proc/sys/kernel/random/uuid)") + if format == nil then + uuid = string.gsub(uuid, "-", "") + end + return uuid end function uci_get_type(type, config, default) - local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. ")") - if (value == nil or value == "") and (default and default ~= "") then - value = default - end - return value + local value = uci:get_first(appname, type, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. ".@" .. type .."[0]." .. config .. ")") + if (value == nil or value == "") and (default and default ~= "") then + value = default + end + return value end function uci_get_type_id(id, config, default) - local value = uci:get(appname, id, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. "." .. id .. "." .. config .. ")") - if (value == nil or value == "") and (default and default ~= "") then - value = default - end - return value + local value = uci:get(appname, id, config, default) or sys.exec("echo -n $(uci -q get " .. appname .. "." .. id .. "." .. config .. ")") + if (value == nil or value == "") and (default and default ~= "") then + value = default + end + return value end local function chmod_755(file) - if file and file ~= "" then - if not fs.access(file, "rwx", "rx", "rx") then - fs.chmod(file, 755) - end - end + if file and file ~= "" then + if not fs.access(file, "rwx", "rx", "rx") then + fs.chmod(file, 755) + end + end end function get_customed_path(e) - return uci_get_type("global_app", e .. "_file") + return uci_get_type("global_app", e .. "_file") end function is_finded(e) - return luci.sys.exec('type -t -p "/bin/%s" -p "%s" "%s"' % {e, get_customed_path(e), e}) ~= "" and true or false + return luci.sys.exec('type -t -p "/bin/%s" -p "%s" "%s"' % {e, get_customed_path(e), e}) ~= "" and true or false end function clone(org) - local function copy(org, res) - for k,v in pairs(org) do - if type(v) ~= "table" then - res[k] = v; - else - res[k] = {}; - copy(v, res[k]) - end - end - end + local function copy(org, res) + for k,v in pairs(org) do + if type(v) ~= "table" then + res[k] = v; + else + res[k] = {}; + copy(v, res[k]) + end + end + end - local res = {} - copy(org, res) - return res + local res = {} + copy(org, res) + return res end local function get_bin_version_cache(file, cmd) - sys.call("mkdir -p /tmp/etc/passwall_tmp") - if fs.access(file) then - chmod_755(file) - local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')") - if fs.access("/tmp/etc/passwall_tmp/" .. md5) then - return sys.exec("echo -n $(cat /tmp/etc/passwall_tmp/%s)" % md5) - else - local version = sys.exec(string.format("echo -n $(%s %s)", file, cmd)) - if version and version ~= "" then - sys.call("echo '" .. version .. "' > " .. "/tmp/etc/passwall_tmp/" .. md5) - return version - end - end - end - return "" + sys.call("mkdir -p /tmp/etc/passwall_tmp") + if fs.access(file) then + chmod_755(file) + local md5 = sys.exec("echo -n $(md5sum " .. file .. " | awk '{print $1}')") + if fs.access("/tmp/etc/passwall_tmp/" .. md5) then + return sys.exec("echo -n $(cat /tmp/etc/passwall_tmp/%s)" % md5) + else + local version = sys.exec(string.format("echo -n $(%s %s)", file, cmd)) + if version and version ~= "" then + sys.call("echo '" .. version .. "' > " .. "/tmp/etc/passwall_tmp/" .. md5) + return version + end + end + end + return "" end function get_app_path(app_name) - local path = uci_get_type("global_app", app_name:gsub("%-","_") .. "_file") - return path + local path = uci_get_type("global_app", app_name:gsub("%-","_") .. "_file") + return path end function get_app_version(app_name, file) - if file == nil then file = get_app_path(app_name) end - return get_bin_version_cache(file, com[app_name].cmd_version) + if file == nil then file = get_app_path(app_name) end + return get_bin_version_cache(file, com[app_name].cmd_version) end local function is_file(path) - if path and #path > 1 then - if sys.exec('[ -f "%s" ] && echo -n 1' % path) == "1" then - return true - end - end - return nil + if path and #path > 1 then + if sys.exec('[ -f "%s" ] && echo -n 1' % path) == "1" then + return true + end + end + return nil end local function is_dir(path) - if path and #path > 1 then - if sys.exec('[ -d "%s" ] && echo -n 1' % path) == "1" then - return true - end - end - return nil + if path and #path > 1 then + if sys.exec('[ -d "%s" ] && echo -n 1' % path) == "1" then + return true + end + end + return nil end local function get_final_dir(path) - if is_dir(path) then - return path - else - return get_final_dir(fs.dirname(path)) - end + if is_dir(path) then + return path + else + return get_final_dir(fs.dirname(path)) + end end local function get_free_space(dir) - if dir == nil then dir = "/" end - if sys.call("df -k " .. dir .. " >/dev/null 2>&1") == 0 then - return tonumber(sys.exec("echo -n $(df -k " .. dir .. " | awk 'NR>1' | awk '{print $4}')")) - end - return 0 + if dir == nil then dir = "/" end + if sys.call("df -k " .. dir .. " >/dev/null 2>&1") == 0 then + return tonumber(sys.exec("echo -n $(df -k " .. dir .. " | awk 'NR>1' | awk '{print $4}')")) + end + return 0 end local function get_file_space(file) - if file == nil then return 0 end - if fs.access(file) then - return tonumber(sys.exec("echo -n $(du -k " .. file .. " | awk '{print $1}')")) - end - return 0 + if file == nil then return 0 end + if fs.access(file) then + return tonumber(sys.exec("echo -n $(du -k " .. file .. " | awk '{print $1}')")) + end + return 0 end function _unpack(t, i) - i = i or 1 - if t[i] ~= nil then return t[i], _unpack(t, i + 1) end + i = i or 1 + if t[i] ~= nil then return t[i], _unpack(t, i + 1) end end function table_join(t, s) - if not s then - s = " " - end - local str = "" - for index, value in ipairs(t) do - str = str .. t[index] .. (index == #t and "" or s) - end - return str + if not s then + s = " " + end + local str = "" + for index, value in ipairs(t) do + str = str .. t[index] .. (index == #t and "" or s) + end + return str end local function exec(cmd, args, writer, timeout) - local os = require "os" - local nixio = require "nixio" + local os = require "os" + local nixio = require "nixio" - local fdi, fdo = nixio.pipe() - local pid = nixio.fork() + local fdi, fdo = nixio.pipe() + local pid = nixio.fork() - if pid > 0 then - fdo:close() + if pid > 0 then + fdo:close() - if writer or timeout then - local starttime = os.time() - while true do - if timeout and os.difftime(os.time(), starttime) >= timeout then - nixio.kill(pid, nixio.const.SIGTERM) - return 1 - end + if writer or timeout then + local starttime = os.time() + while true do + if timeout and os.difftime(os.time(), starttime) >= timeout then + nixio.kill(pid, nixio.const.SIGTERM) + return 1 + end - if writer then - local buffer = fdi:read(2048) - if buffer and #buffer > 0 then - writer(buffer) - end - end + if writer then + local buffer = fdi:read(2048) + if buffer and #buffer > 0 then + writer(buffer) + end + end - local wpid, stat, code = nixio.waitpid(pid, "nohang") + local wpid, stat, code = nixio.waitpid(pid, "nohang") - if wpid and stat == "exited" then return code end + if wpid and stat == "exited" then return code end - if not writer and timeout then nixio.nanosleep(1) end - end - else - local wpid, stat, code = nixio.waitpid(pid) - return wpid and stat == "exited" and code - end - elseif pid == 0 then - nixio.dup(fdo, nixio.stdout) - fdi:close() - fdo:close() - nixio.exece(cmd, args, nil) - nixio.stdout:close() - os.exit(1) - end + if not writer and timeout then nixio.nanosleep(1) end + end + else + local wpid, stat, code = nixio.waitpid(pid) + return wpid and stat == "exited" and code + end + elseif pid == 0 then + nixio.dup(fdo, nixio.stdout) + fdi:close() + fdo:close() + nixio.exece(cmd, args, nil) + nixio.stdout:close() + os.exit(1) + end end local function compare_versions(ver1, comp, ver2) - local table = table + local table = table - if not ver1 then ver1 = "" end - if not ver2 then ver2 = "" end + if not ver1 then ver1 = "" end + if not ver2 then ver2 = "" end - local av1 = util.split(ver1, "[%.%-]", nil, true) - local av2 = util.split(ver2, "[%.%-]", nil, true) + local av1 = util.split(ver1, "[%.%-]", nil, true) + local av2 = util.split(ver2, "[%.%-]", nil, true) - local max = table.getn(av1) - local n2 = table.getn(av2) - if (max < n2) then max = n2 end + local max = table.getn(av1) + local n2 = table.getn(av2) + if (max < n2) then max = n2 end - for i = 1, max, 1 do - local s1 = tonumber(av1[i] or 0) or 0 - local s2 = tonumber(av2[i] or 0) or 0 + for i = 1, max, 1 do + local s1 = tonumber(av1[i] or 0) or 0 + local s2 = tonumber(av2[i] or 0) or 0 - if comp == "~=" and (s1 ~= s2) then return true end - if (comp == "<" or comp == "<=") and (s1 < s2) then return true end - if (comp == ">" or comp == ">=") and (s1 > s2) then return true end - if (s1 ~= s2) then return false end - end + if comp == "~=" and (s1 ~= s2) then return true end + if (comp == "<" or comp == "<=") and (s1 < s2) then return true end + if (comp == ">" or comp == ">=") and (s1 > s2) then return true end + if (s1 ~= s2) then return false end + end - return not (comp == "<" or comp == ">") + return not (comp == "<" or comp == ">") end local function auto_get_arch() - local arch = nixio.uname().machine or "" - if not OPENWRT_ARCH and fs.access("/usr/lib/os-release") then - OPENWRT_ARCH = sys.exec("echo -n $(grep 'OPENWRT_ARCH' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}')") - if OPENWRT_ARCH == "" then OPENWRT_ARCH = nil end - end - if not DISTRIB_ARCH and fs.access("/etc/openwrt_release") then - DISTRIB_ARCH = sys.exec("echo -n $(grep 'DISTRIB_ARCH' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}')") - if DISTRIB_ARCH == "" then DISTRIB_ARCH = nil end - end + local arch = nixio.uname().machine or "" + if not OPENWRT_ARCH and fs.access("/usr/lib/os-release") then + OPENWRT_ARCH = sys.exec("echo -n $(grep 'OPENWRT_ARCH' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}')") + if OPENWRT_ARCH == "" then OPENWRT_ARCH = nil end + end + if not DISTRIB_ARCH and fs.access("/etc/openwrt_release") then + DISTRIB_ARCH = sys.exec("echo -n $(grep 'DISTRIB_ARCH' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}')") + if DISTRIB_ARCH == "" then DISTRIB_ARCH = nil end + end - if arch:match("^i[%d]86$") then - arch = "x86" - elseif arch:match("armv5") then -- armv5l - arch = "armv5" - elseif arch:match("armv6") then - arch = "armv6" - elseif arch:match("armv7") then -- armv7l - arch = "armv7" - end + if arch:match("^i[%d]86$") then + arch = "x86" + elseif arch:match("armv5") then -- armv5l + arch = "armv5" + elseif arch:match("armv6") then + arch = "armv6" + elseif arch:match("armv7") then -- armv7l + arch = "armv7" + end - if OPENWRT_ARCH or DISTRIB_ARCH then - if arch == "mips" then - if OPENWRT_ARCH and OPENWRT_ARCH:match("mipsel") == "mipsel" - or DISTRIB_ARCH and DISTRIB_ARCH:match("mipsel") == "mipsel" then - arch = "mipsel" - end - elseif arch == "armv7" then - if OPENWRT_ARCH and not OPENWRT_ARCH:match("vfp") and not OPENWRT_ARCH:match("neon") - or DISTRIB_ARCH and not DISTRIB_ARCH:match("vfp") and not DISTRIB_ARCH:match("neon") then - arch = "armv5" - end - end - end + if OPENWRT_ARCH or DISTRIB_ARCH then + if arch == "mips" then + if OPENWRT_ARCH and OPENWRT_ARCH:match("mipsel") == "mipsel" + or DISTRIB_ARCH and DISTRIB_ARCH:match("mipsel") == "mipsel" then + arch = "mipsel" + end + elseif arch == "armv7" then + if OPENWRT_ARCH and not OPENWRT_ARCH:match("vfp") and not OPENWRT_ARCH:match("neon") + or DISTRIB_ARCH and not DISTRIB_ARCH:match("vfp") and not DISTRIB_ARCH:match("neon") then + arch = "armv5" + end + end + end - return util.trim(arch) + return util.trim(arch) end local default_file_tree = { - x86_64 = "amd64", - x86 = "386", - aarch64 = "arm64", - mips = "mips", - mipsel = "mipsle", - armv5 = "arm.*5", - armv6 = "arm.*6[^4]*", - armv7 = "arm.*7", - armv8 = "arm64" + x86_64 = "amd64", + x86 = "386", + aarch64 = "arm64", + mips = "mips", + mipsel = "mipsle", + armv5 = "arm.*5", + armv6 = "arm.*6[^4]*", + armv7 = "arm.*7", + armv8 = "arm64" } local function get_api_json(url) - local jsonc = require "luci.jsonc" - local return_code, content = curl_logic(url, nil, curl_args) - if return_code ~= 0 or content == "" then return {} end - return jsonc.parse(content) or {} + local jsonc = require "luci.jsonc" + local return_code, content = curl_logic(url, nil, curl_args) + if return_code ~= 0 or content == "" then return {} end + return jsonc.parse(content) or {} end local function check_path(app_name) - local path = get_app_path(app_name) or "" - if path == "" then - return { - code = 1, - error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", app_name) - } - end - return { - code = 0, - app_path = path - } + local path = get_app_path(app_name) or "" + if path == "" then + return { + code = 1, + error = i18n.translatef("You did not fill in the %s path. Please save and apply then update manually.", app_name) + } + end + return { + code = 0, + app_path = path + } end function to_check(arch, app_name) - local result = check_path(app_name) - if result.code ~= 0 then - return result - end + local result = check_path(app_name) + if result.code ~= 0 then + return result + end - if not arch or arch == "" then arch = auto_get_arch() end + if not arch or arch == "" then arch = auto_get_arch() end - local file_tree = com[app_name].file_tree[arch] or default_file_tree[arch] or "" + local file_tree = com[app_name].file_tree[arch] or default_file_tree[arch] or "" - if file_tree == "" then - return { - code = 1, - error = i18n.translate("Can't determine ARCH, or ARCH not supported.") - } - end + if file_tree == "" then + return { + code = 1, + error = i18n.translate("Can't determine ARCH, or ARCH not supported.") + } + end - local local_version = get_app_version(app_name) - local match_file_name = string.format(com[app_name].match_fmt_str, file_tree) - local json = get_api_json(com[app_name]:get_url()) + local local_version = get_app_version(app_name) + local match_file_name = string.format(com[app_name].match_fmt_str, file_tree) + local json = get_api_json(com[app_name]:get_url()) - if #json > 0 then - json = json[1] - end + if #json > 0 then + json = json[1] + end - if json.tag_name == nil then - return { - code = 1, - error = i18n.translate("Get remote version info failed.") - } - end + if json.tag_name == nil then + return { + code = 1, + error = i18n.translate("Get remote version info failed.") + } + end - local remote_version = json.tag_name - local has_update = compare_versions(local_version:match("[^v]+"), "<", remote_version:match("[^v]+")) + local remote_version = json.tag_name + local has_update = compare_versions(local_version:match("[^v]+"), "<", remote_version:match("[^v]+")) - if not has_update then - return { - code = 0, - local_version = local_version, - remote_version = remote_version - } - end + if not has_update then + return { + code = 0, + local_version = local_version, + remote_version = remote_version + } + end - local asset = {} - for _, v in ipairs(json.assets) do - if v.name and v.name:match(match_file_name) then - asset = v - break - end - end - if not asset.browser_download_url then - return { - code = 1, - local_version = local_version, - remote_version = remote_version, - html_url = json.html_url, - data = asset, - error = i18n.translate("New version found, but failed to get new version download url.") - } - end + local asset = {} + for _, v in ipairs(json.assets) do + if v.name and v.name:match(match_file_name) then + asset = v + break + end + end + if not asset.browser_download_url then + return { + code = 1, + local_version = local_version, + remote_version = remote_version, + html_url = json.html_url, + data = asset, + error = i18n.translate("New version found, but failed to get new version download url.") + } + end - return { - code = 0, - has_update = true, - local_version = local_version, - remote_version = remote_version, - html_url = json.html_url, - data = asset - } + return { + code = 0, + has_update = true, + local_version = local_version, + remote_version = remote_version, + html_url = json.html_url, + data = asset + } end function to_download(app_name, url, size) - local result = check_path(app_name) - if result.code ~= 0 then - return result - end + local result = check_path(app_name) + if result.code ~= 0 then + return result + end - if not url or url == "" then - return {code = 1, error = i18n.translate("Download url is required.")} - end + if not url or url == "" then + return {code = 1, error = i18n.translate("Download url is required.")} + end - sys.call("/bin/rm -f /tmp/".. app_name .."_download.*") + sys.call("/bin/rm -f /tmp/".. app_name .."_download.*") - local tmp_file = util.trim(util.exec("mktemp -u -t ".. app_name .."_download.XXXXXX")) + local tmp_file = util.trim(util.exec("mktemp -u -t ".. app_name .."_download.XXXXXX")) - if size then - local kb1 = get_free_space("/tmp") - if tonumber(size) > tonumber(kb1) then - return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} - end - end + if size then + local kb1 = get_free_space("/tmp") + if tonumber(size) > tonumber(kb1) then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end + end - local return_code, result = curl_logic(url, tmp_file, curl_args) - result = return_code == 0 + local return_code, result = curl_logic(url, tmp_file, curl_args) + result = return_code == 0 - if not result then - exec("/bin/rm", {"-f", tmp_file}) - return { - code = 1, - error = i18n.translatef("File download failed or timed out: %s", url) - } - end + if not result then + exec("/bin/rm", {"-f", tmp_file}) + return { + code = 1, + error = i18n.translatef("File download failed or timed out: %s", url) + } + end - return {code = 0, file = tmp_file, zip = com[app_name].zipped } + return {code = 0, file = tmp_file, zip = com[app_name].zipped } end function to_extract(app_name, file, subfix) - local result = check_path(app_name) - if result.code ~= 0 then - return result - end + local result = check_path(app_name) + if result.code ~= 0 then + return result + end - if not file or file == "" or not fs.access(file) then - return {code = 1, error = i18n.translate("File path required.")} - end + if not file or file == "" or not fs.access(file) then + return {code = 1, error = i18n.translate("File path required.")} + end - if sys.exec("echo -n $(opkg list-installed | grep -c unzip)") ~= "1" then - exec("/bin/rm", {"-f", file}) - return { - code = 1, - error = i18n.translate("Not installed unzip, Can't unzip!") - } - end + if sys.exec("echo -n $(opkg list-installed | grep -c unzip)") ~= "1" then + exec("/bin/rm", {"-f", file}) + return { + code = 1, + error = i18n.translate("Not installed unzip, Can't unzip!") + } + end - sys.call("/bin/rm -rf /tmp/".. app_name .."_extract.*") + sys.call("/bin/rm -rf /tmp/".. app_name .."_extract.*") - local new_file_size = get_file_space(file) - local tmp_free_size = get_free_space("/tmp") - if tmp_free_size <= 0 or tmp_free_size <= new_file_size then - return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} - end + local new_file_size = get_file_space(file) + local tmp_free_size = get_free_space("/tmp") + if tmp_free_size <= 0 or tmp_free_size <= new_file_size then + return {code = 1, error = i18n.translatef("%s not enough space.", "/tmp")} + end - local tmp_dir = util.trim(util.exec("mktemp -d -t ".. app_name .."_extract.XXXXXX")) + local tmp_dir = util.trim(util.exec("mktemp -d -t ".. app_name .."_extract.XXXXXX")) - local output = {} - exec("/usr/bin/unzip", {"-o", file, app_name, "-d", tmp_dir}, - function(chunk) output[#output + 1] = chunk end) + local output = {} + exec("/usr/bin/unzip", {"-o", file, app_name, "-d", tmp_dir}, + function(chunk) output[#output + 1] = chunk end) - local files = util.split(table.concat(output)) + local files = util.split(table.concat(output)) - exec("/bin/rm", {"-f", file}) + exec("/bin/rm", {"-f", file}) - return {code = 0, file = tmp_dir} + return {code = 0, file = tmp_dir} end function to_move(app_name,file) - local result = check_path(app_name) - if result.code ~= 0 then - return result - end + local result = check_path(app_name) + if result.code ~= 0 then + return result + end - local app_path = result.app_path - local bin_path = file - local cmd_rm_tmp = "/bin/rm -rf /tmp/" .. app_name .. "_download.*" - if fs.stat(file, "type") == "dir" then - bin_path = file .. "/" .. app_name - cmd_rm_tmp = "/bin/rm -rf /tmp/" .. app_name .. "_extract.*" - end + local app_path = result.app_path + local bin_path = file + local cmd_rm_tmp = "/bin/rm -rf /tmp/" .. app_name .. "_download.*" + if fs.stat(file, "type") == "dir" then + bin_path = file .. "/" .. app_name + cmd_rm_tmp = "/bin/rm -rf /tmp/" .. app_name .. "_extract.*" + end - if not file or file == "" then - sys.call(cmd_rm_tmp) - return {code = 1, error = i18n.translate("Client file is required.")} - end + if not file or file == "" then + sys.call(cmd_rm_tmp) + return {code = 1, error = i18n.translate("Client file is required.")} + end - local new_version = get_app_version(app_name, bin_path) - if new_version == "" then - sys.call(cmd_rm_tmp) - return { - code = 1, - error = i18n.translate("The client file is not suitable for current device.")..app_name.."__"..bin_path - } - end + local new_version = get_app_version(app_name, bin_path) + if new_version == "" then + sys.call(cmd_rm_tmp) + return { + code = 1, + error = i18n.translate("The client file is not suitable for current device.")..app_name.."__"..bin_path + } + end - local flag = sys.call('pgrep -af "passwall/.*'.. app_name ..'" >/dev/null') - if flag == 0 then - sys.call("/etc/init.d/passwall stop") - end + local flag = sys.call('pgrep -af "passwall/.*'.. app_name ..'" >/dev/null') + if flag == 0 then + sys.call("/etc/init.d/passwall stop") + end - local old_app_size = 0 - if fs.access(app_path) then - old_app_size = get_file_space(app_path) - end - local new_app_size = get_file_space(bin_path) - local final_dir = get_final_dir(app_path) - local final_dir_free_size = get_free_space(final_dir) - if final_dir_free_size > 0 then - final_dir_free_size = final_dir_free_size + old_app_size - if new_app_size > final_dir_free_size then - sys.call(cmd_rm_tmp) - return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)} - end - end + local old_app_size = 0 + if fs.access(app_path) then + old_app_size = get_file_space(app_path) + end + local new_app_size = get_file_space(bin_path) + local final_dir = get_final_dir(app_path) + local final_dir_free_size = get_free_space(final_dir) + if final_dir_free_size > 0 then + final_dir_free_size = final_dir_free_size + old_app_size + if new_app_size > final_dir_free_size then + sys.call(cmd_rm_tmp) + return {code = 1, error = i18n.translatef("%s not enough space.", final_dir)} + end + end - result = exec("/bin/mv", { "-f", bin_path, app_path }, nil, command_timeout) == 0 + result = exec("/bin/mv", { "-f", bin_path, app_path }, nil, command_timeout) == 0 - sys.call(cmd_rm_tmp) - if flag == 0 then - sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &") - end + sys.call(cmd_rm_tmp) + if flag == 0 then + sys.call("/etc/init.d/passwall restart >/dev/null 2>&1 &") + end - if not result or not fs.access(app_path) then - return { - code = 1, - error = i18n.translatef("Can't move new file to path: %s", app_path) - } - end + if not result or not fs.access(app_path) then + return { + code = 1, + error = i18n.translatef("Can't move new file to path: %s", app_path) + } + end - return {code = 0} + return {code = 0} end diff --git a/luci-app-passwall/luasrc/passwall/com.lua b/luci-app-passwall/luasrc/passwall/com.lua index cb8968891..53ed0a7de 100644 --- a/luci-app-passwall/luasrc/passwall/com.lua +++ b/luci-app-passwall/luasrc/passwall/com.lua @@ -1,99 +1,99 @@ local _M = {} local function gh_release_url(self) - return "https://api.github.com/repos/" .. self.repo .. "/releases/latest" + return "https://api.github.com/repos/" .. self.repo .. "/releases/latest" end local function gh_pre_release_url(self) - return "https://api.github.com/repos/" .. self.repo .. "/releases?per_page=1" + return "https://api.github.com/repos/" .. self.repo .. "/releases?per_page=1" end _M.brook = { - name = "Brook", - repo = "txthinking/brook", - get_url = gh_release_url, - cmd_version = "-v | awk '{print $3}'", - zipped = false, - default_path = "/usr/bin/brook", - match_fmt_str = "linux_%s$", - file_tree = {} + name = "Brook", + repo = "txthinking/brook", + get_url = gh_release_url, + cmd_version = "-v | awk '{print $3}'", + zipped = false, + default_path = "/usr/bin/brook", + match_fmt_str = "linux_%s$", + file_tree = {} } _M.hysteria = { - name = "Hysteria", - repo = "HyNetwork/hysteria", - get_url = gh_release_url, - cmd_version = "-v | awk '{print $3}'", - zipped = false, - default_path = "/usr/bin/hysteria", - match_fmt_str = "linux%%-%s$", - file_tree = { - armv6 = "arm", - armv7 = "arm" - } + name = "Hysteria", + repo = "HyNetwork/hysteria", + get_url = gh_release_url, + cmd_version = "-v | awk '{print $3}'", + zipped = false, + default_path = "/usr/bin/hysteria", + match_fmt_str = "linux%%-%s$", + file_tree = { + armv6 = "arm", + armv7 = "arm" + } } _M["trojan-go"] = { - name = "Trojan-Go", - repo = "p4gefau1t/trojan-go", - get_url = gh_release_url, - cmd_version = "-version | awk '{print $2}' | sed -n 1P", - zipped = true, - default_path = "/usr/bin/trojan-go", - match_fmt_str = "linux%%-%s%%.zip", - file_tree = { - aarch64 = "armv8", - armv8 = "armv8", - mips = "mips%-hardfloat", - mipsel = "mipsle%-hardfloat" - } + name = "Trojan-Go", + repo = "p4gefau1t/trojan-go", + get_url = gh_release_url, + cmd_version = "-version | awk '{print $2}' | sed -n 1P", + zipped = true, + default_path = "/usr/bin/trojan-go", + match_fmt_str = "linux%%-%s%%.zip", + file_tree = { + aarch64 = "armv8", + armv8 = "armv8", + mips = "mips%-hardfloat", + mipsel = "mipsle%-hardfloat" + } } _M.v2ray = { - name = "V2ray", - repo = "v2fly/v2ray-core", - get_url = gh_pre_release_url, - cmd_version = "version | awk '{print $2}' | sed -n 1P", - zipped = true, - default_path = "/usr/bin/v2ray", - match_fmt_str = "linux%%-%s", - file_tree = { - x86_64 = "64", - x86 = "32", - mips = "mips32", - mipsel = "mips32le" - } + name = "V2ray", + repo = "v2fly/v2ray-core", + get_url = gh_pre_release_url, + cmd_version = "version | awk '{print $2}' | sed -n 1P", + zipped = true, + default_path = "/usr/bin/v2ray", + match_fmt_str = "linux%%-%s", + file_tree = { + x86_64 = "64", + x86 = "32", + mips = "mips32", + mipsel = "mips32le" + } } _M.xray = { - name = "Xray", - repo = "XTLS/Xray-core", - get_url = gh_pre_release_url, - cmd_version = _M.v2ray.cmd_version, - zipped = true, - default_path = "/usr/bin/xray", - match_fmt_str = _M.v2ray.match_fmt_str, - file_tree = _M.v2ray.file_tree + name = "Xray", + repo = "XTLS/Xray-core", + get_url = gh_pre_release_url, + cmd_version = _M.v2ray.cmd_version, + zipped = true, + default_path = "/usr/bin/xray", + match_fmt_str = _M.v2ray.match_fmt_str, + file_tree = _M.v2ray.file_tree } _M["chinadns-ng"] = { - name = "ChinaDNS-NG", - repo = "zfl9/chinadns-ng", - get_url = gh_pre_release_url, - cmd_version = "-V | awk '{print $2}'", - zipped = false, - default_path = "/usr/bin/chinadns-ng", - match_fmt_str = "%s$", - file_tree = { - x86_64 = "x86_64", - x86 = "i686", - mipsel = "mipsel", - aarch64 = "aarch64", - armv5 = "arm%-eabi", - armv6 = "armv6%-eabihf", - armv7 = "armv7l%-eabihf", - armv8 = "aarch64" - } + name = "ChinaDNS-NG", + repo = "zfl9/chinadns-ng", + get_url = gh_pre_release_url, + cmd_version = "-V | awk '{print $2}'", + zipped = false, + default_path = "/usr/bin/chinadns-ng", + match_fmt_str = "%s$", + file_tree = { + x86_64 = "x86_64", + x86 = "i686", + mipsel = "mipsel", + aarch64 = "aarch64", + armv5 = "arm%-eabi", + armv6 = "armv6%-eabihf", + armv7 = "armv7l%-eabihf", + armv8 = "aarch64" + } } return _M diff --git a/luci-app-passwall/luasrc/passwall/server_app.lua b/luci-app-passwall/luasrc/passwall/server_app.lua index a54608c03..d93de0f3f 100644 --- a/luci-app-passwall/luasrc/passwall/server_app.lua +++ b/luci-app-passwall/luasrc/passwall/server_app.lua @@ -18,215 +18,215 @@ local ip6t_bin = sys.exec("echo -n $(/usr/share/passwall/iptables.sh get_ip6t_bi local nft_flag = api.is_finded("fw4") and "1" or "0" local function log(...) - local f, err = io.open(LOG_APP_FILE, "a") - if f and err == nil then - local str = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") - f:write(str .. "\n") - f:close() - end + local f, err = io.open(LOG_APP_FILE, "a") + if f and err == nil then + local str = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") + f:write(str .. "\n") + f:close() + end end local function cmd(cmd) - sys.call(cmd) + sys.call(cmd) end local function ipt(arg) - cmd(ipt_bin .. " -w " .. arg) + cmd(ipt_bin .. " -w " .. arg) end local function ip6t(arg) - cmd(ip6t_bin .. " -w " .. arg) + cmd(ip6t_bin .. " -w " .. arg) end local function ln_run(s, d, command, output) - if not output then - output = "/dev/null" - end - d = TMP_BIN_PATH .. "/" .. d - cmd(string.format('[ ! -f "%s" ] && ln -s %s %s 2>/dev/null', d, s, d)) - return string.format("%s >%s 2>&1 &", d .. " " ..command, output) + if not output then + output = "/dev/null" + end + d = TMP_BIN_PATH .. "/" .. d + cmd(string.format('[ ! -f "%s" ] && ln -s %s %s 2>/dev/null', d, s, d)) + return string.format("%s >%s 2>&1 &", d .. " " ..command, output) end local function gen_include() - cmd(string.format("echo '#!/bin/sh' > /tmp/etc/%s.include", CONFIG)) - if nft_flag == "1" then - cmd("echo \"\" > " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft") - local nft_cmd="for chain in $(nft -a list chains |grep -E \"chain PSW-SERVER\" |awk -F ' ' '{print$2}'); do\n nft list chain inet fw4 ${chain} >> " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft\n done" - cmd(nft_cmd) - end - local function extract_rules(n, a) - local _ipt = ipt_bin - if n == "6" then - _ipt = ip6t_bin - end - local result = "*" .. a - result = result .. "\n" .. sys.exec(_ipt .. '-save -t ' .. a .. ' | grep "PSW-SERVER" | sed -e "s/^-A \\(INPUT\\)/-I \\1 1/"') - result = result .. "COMMIT" - return result - end - local f, err = io.open("/tmp/etc/" .. CONFIG .. ".include", "a") - if f and err == nil then - if nft_flag == "0" then - f:write(ipt_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n") - f:write(ipt_bin .. '-restore -n <<-EOT' .. "\n") - f:write(extract_rules("4", "filter") .. "\n") - f:write("EOT" .. "\n") - f:write(ip6t_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ip6t_bin .. '-restore -c' .. "\n") - f:write(ip6t_bin .. '-restore -n <<-EOT' .. "\n") - f:write(extract_rules("6", "filter") .. "\n") - f:write("EOT" .. "\n") - f:close() - else - f:write("nft -f " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft\n") - f:write("nft insert rule inet fw4 input position 0 counter jump PSW-SERVER") - f:close() - end - end + cmd(string.format("echo '#!/bin/sh' > /tmp/etc/%s.include", CONFIG)) + if nft_flag == "1" then + cmd("echo \"\" > " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft") + local nft_cmd="for chain in $(nft -a list chains |grep -E \"chain PSW-SERVER\" |awk -F ' ' '{print$2}'); do\n nft list chain inet fw4 ${chain} >> " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft\n done" + cmd(nft_cmd) + end + local function extract_rules(n, a) + local _ipt = ipt_bin + if n == "6" then + _ipt = ip6t_bin + end + local result = "*" .. a + result = result .. "\n" .. sys.exec(_ipt .. '-save -t ' .. a .. ' | grep "PSW-SERVER" | sed -e "s/^-A \\(INPUT\\)/-I \\1 1/"') + result = result .. "COMMIT" + return result + end + local f, err = io.open("/tmp/etc/" .. CONFIG .. ".include", "a") + if f and err == nil then + if nft_flag == "0" then + f:write(ipt_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ipt_bin .. '-restore -c' .. "\n") + f:write(ipt_bin .. '-restore -n <<-EOT' .. "\n") + f:write(extract_rules("4", "filter") .. "\n") + f:write("EOT" .. "\n") + f:write(ip6t_bin .. '-save -c | grep -v "PSW-SERVER" | ' .. ip6t_bin .. '-restore -c' .. "\n") + f:write(ip6t_bin .. '-restore -n <<-EOT' .. "\n") + f:write(extract_rules("6", "filter") .. "\n") + f:write("EOT" .. "\n") + f:close() + else + f:write("nft -f " .. CONFIG_PATH .. "/" .. CONFIG .. ".nft\n") + f:write("nft insert rule inet fw4 input position 0 counter jump PSW-SERVER") + f:close() + end + end end local function start() - local enabled = tonumber(uci:get(CONFIG, "@global[0]", "enable") or 0) - if enabled == nil or enabled == 0 then - return - end - cmd(string.format("mkdir -p %s %s", CONFIG_PATH, TMP_BIN_PATH)) - cmd(string.format("touch %s", LOG_APP_FILE)) - if nft_flag == "0" then - ipt("-N PSW-SERVER") - ipt("-I INPUT -j PSW-SERVER") - ip6t("-N PSW-SERVER") - ip6t("-I INPUT -j PSW-SERVER") - else - cmd("nft add chain inet fw4 PSW-SERVER\n") - cmd("nft insert rule inet fw4 input position 0 counter jump PSW-SERVER") - end - uci:foreach(CONFIG, "user", function(user) - local id = user[".name"] - local enable = user.enable - if enable and tonumber(enable) == 1 then - local enable_log = user.log - local log_path = nil - if enable_log and enable_log == "1" then - log_path = CONFIG_PATH .. "/" .. id .. ".log" - else - log_path = nil - end - local remarks = user.remarks - local port = tonumber(user.port) - local bin - local config = {} - local config_file = CONFIG_PATH .. "/" .. id .. ".json" - local udp_forward = 1 - local type = user.type or "" - if type == "Socks" then - local auth = "" - if user.auth and user.auth == "1" then - local username = user.username or "" - local password = user.password or "" - if username ~= "" and password ~= "" then - username = "-u " .. username - password = "-P " .. password - auth = username .. " " .. password - end - end - bin = ln_run("/usr/bin/microsocks", "microsocks_" .. id, string.format("-i :: -p %s %s", port, auth), log_path) - elseif type == "SS" or type == "SSR" then - config = require(require_dir .. "util_shadowsocks").gen_config_server(user) - local udp_param = "" - udp_forward = tonumber(user.udp_forward) or 1 - if udp_forward == 1 then - udp_param = "-u" - end - type = type:lower() - bin = ln_run("/usr/bin/" .. type .. "-server", type .. "-server", "-c " .. config_file .. " " .. udp_param, log_path) - elseif type == "SS-Rust" then - config = require(require_dir .. "util_shadowsocks").gen_config_server(user) - bin = ln_run("/usr/bin/ssserver", "ssserver", "-c " .. config_file, log_path) - elseif type == "V2ray" then - config = require(require_dir .. "util_xray").gen_config_server(user) - bin = ln_run(api.get_app_path("v2ray"), "v2ray", "run -c " .. config_file, log_path) - elseif type == "Xray" then - config = require(require_dir .. "util_xray").gen_config_server(user) - bin = ln_run(api.get_app_path("xray"), "xray", "run -c " .. config_file, log_path) - elseif type == "Trojan" then - config = require(require_dir .. "util_trojan").gen_config_server(user) - bin = ln_run("/usr/sbin/trojan", "trojan", "-c " .. config_file, log_path) - elseif type == "Trojan-Plus" then - config = require(require_dir .. "util_trojan").gen_config_server(user) - bin = ln_run("/usr/sbin/trojan-plus", "trojan-plus", "-c " .. config_file, log_path) - elseif type == "Trojan-Go" then - config = require(require_dir .. "util_trojan").gen_config_server(user) - bin = ln_run(api.get_app_path("trojan-go"), "trojan-go", "-config " .. config_file, log_path) - elseif type == "Brook" then - local brook_protocol = user.protocol - local brook_password = user.password - local brook_path = user.ws_path or "/ws" - local brook_path_arg = "" - if brook_protocol == "wsserver" and brook_path then - brook_path_arg = " --path " .. brook_path - end - bin = ln_run(api.get_app_path("brook"), "brook_" .. id, string.format("--debug %s -l :%s -p %s%s", brook_protocol, port, brook_password, brook_path_arg), log_path) - elseif type == "Hysteria" then - config = require(require_dir .. "util_hysteria").gen_config_server(user) - bin = ln_run(api.get_app_path("hysteria"), "hysteria", "-c " .. config_file .. " server", log_path) - end + local enabled = tonumber(uci:get(CONFIG, "@global[0]", "enable") or 0) + if enabled == nil or enabled == 0 then + return + end + cmd(string.format("mkdir -p %s %s", CONFIG_PATH, TMP_BIN_PATH)) + cmd(string.format("touch %s", LOG_APP_FILE)) + if nft_flag == "0" then + ipt("-N PSW-SERVER") + ipt("-I INPUT -j PSW-SERVER") + ip6t("-N PSW-SERVER") + ip6t("-I INPUT -j PSW-SERVER") + else + cmd("nft add chain inet fw4 PSW-SERVER\n") + cmd("nft insert rule inet fw4 input position 0 counter jump PSW-SERVER") + end + uci:foreach(CONFIG, "user", function(user) + local id = user[".name"] + local enable = user.enable + if enable and tonumber(enable) == 1 then + local enable_log = user.log + local log_path = nil + if enable_log and enable_log == "1" then + log_path = CONFIG_PATH .. "/" .. id .. ".log" + else + log_path = nil + end + local remarks = user.remarks + local port = tonumber(user.port) + local bin + local config = {} + local config_file = CONFIG_PATH .. "/" .. id .. ".json" + local udp_forward = 1 + local type = user.type or "" + if type == "Socks" then + local auth = "" + if user.auth and user.auth == "1" then + local username = user.username or "" + local password = user.password or "" + if username ~= "" and password ~= "" then + username = "-u " .. username + password = "-P " .. password + auth = username .. " " .. password + end + end + bin = ln_run("/usr/bin/microsocks", "microsocks_" .. id, string.format("-i :: -p %s %s", port, auth), log_path) + elseif type == "SS" or type == "SSR" then + config = require(require_dir .. "util_shadowsocks").gen_config_server(user) + local udp_param = "" + udp_forward = tonumber(user.udp_forward) or 1 + if udp_forward == 1 then + udp_param = "-u" + end + type = type:lower() + bin = ln_run("/usr/bin/" .. type .. "-server", type .. "-server", "-c " .. config_file .. " " .. udp_param, log_path) + elseif type == "SS-Rust" then + config = require(require_dir .. "util_shadowsocks").gen_config_server(user) + bin = ln_run("/usr/bin/ssserver", "ssserver", "-c " .. config_file, log_path) + elseif type == "V2ray" then + config = require(require_dir .. "util_xray").gen_config_server(user) + bin = ln_run(api.get_app_path("v2ray"), "v2ray", "run -c " .. config_file, log_path) + elseif type == "Xray" then + config = require(require_dir .. "util_xray").gen_config_server(user) + bin = ln_run(api.get_app_path("xray"), "xray", "run -c " .. config_file, log_path) + elseif type == "Trojan" then + config = require(require_dir .. "util_trojan").gen_config_server(user) + bin = ln_run("/usr/sbin/trojan", "trojan", "-c " .. config_file, log_path) + elseif type == "Trojan-Plus" then + config = require(require_dir .. "util_trojan").gen_config_server(user) + bin = ln_run("/usr/sbin/trojan-plus", "trojan-plus", "-c " .. config_file, log_path) + elseif type == "Trojan-Go" then + config = require(require_dir .. "util_trojan").gen_config_server(user) + bin = ln_run(api.get_app_path("trojan-go"), "trojan-go", "-config " .. config_file, log_path) + elseif type == "Brook" then + local brook_protocol = user.protocol + local brook_password = user.password + local brook_path = user.ws_path or "/ws" + local brook_path_arg = "" + if brook_protocol == "wsserver" and brook_path then + brook_path_arg = " --path " .. brook_path + end + bin = ln_run(api.get_app_path("brook"), "brook_" .. id, string.format("--debug %s -l :%s -p %s%s", brook_protocol, port, brook_password, brook_path_arg), log_path) + elseif type == "Hysteria" then + config = require(require_dir .. "util_hysteria").gen_config_server(user) + bin = ln_run(api.get_app_path("hysteria"), "hysteria", "-c " .. config_file .. " server", log_path) + end - if next(config) then - local f, err = io.open(config_file, "w") - if f and err == nil then - f:write(jsonc.stringify(config, 1)) - f:close() - end - log(string.format("%s %s 生成配置文件并运行 - %s", remarks, port, config_file)) - end + if next(config) then + local f, err = io.open(config_file, "w") + if f and err == nil then + f:write(jsonc.stringify(config, 1)) + f:close() + end + log(string.format("%s %s 生成配置文件并运行 - %s", remarks, port, config_file)) + end - if bin then - cmd(bin) - end + if bin then + cmd(bin) + end - local bind_local = user.bind_local or 0 - if bind_local and tonumber(bind_local) ~= 1 then - if nft_flag == "0" then - ipt(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - ip6t(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - if udp_forward == 1 then - ipt(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - ip6t(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) - end - else - cmd(string.format('nft add rule inet fw4 PSW-SERVER meta l4proto tcp tcp dport {%s} accept', port)) - if udp_forward == 1 then - cmd(string.format('nft add rule inet fw4 PSW-SERVER meta l4proto udp udp dport {%s} accept', port)) - end - end - end - end - end) - gen_include() + local bind_local = user.bind_local or 0 + if bind_local and tonumber(bind_local) ~= 1 then + if nft_flag == "0" then + ipt(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + ip6t(string.format('-A PSW-SERVER -p tcp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + if udp_forward == 1 then + ipt(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + ip6t(string.format('-A PSW-SERVER -p udp --dport %s -m comment --comment "%s" -j ACCEPT', port, remarks)) + end + else + cmd(string.format('nft add rule inet fw4 PSW-SERVER meta l4proto tcp tcp dport {%s} accept', port)) + if udp_forward == 1 then + cmd(string.format('nft add rule inet fw4 PSW-SERVER meta l4proto udp udp dport {%s} accept', port)) + end + end + end + end + end) + gen_include() end local function stop() - cmd(string.format("/bin/busybox top -bn1 | grep -v 'grep' | grep '%s/' | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1", CONFIG_PATH)) - if nft_flag == "0" then - ipt("-D INPUT -j PSW-SERVER 2>/dev/null") - ipt("-F PSW-SERVER 2>/dev/null") - ipt("-X PSW-SERVER 2>/dev/null") - ip6t("-D INPUT -j PSW-SERVER 2>/dev/null") - ip6t("-F PSW-SERVER 2>/dev/null") - ip6t("-X PSW-SERVER 2>/dev/null") - else - nft_cmd="handles=$(nft -a list chain inet fw4 input | grep -E \"PSW-SERVER\" | awk -F '# handle ' '{print$2}')\n for handle in $handles; do\n nft delete rule inet fw4 input handle ${handle} 2>/dev/null\n done" - cmd(nft_cmd) - cmd("nft flush chain inet fw4 PSW-SERVER 2>/dev/null") - cmd("nft delete chain inet fw4 PSW-SERVER 2>/dev/null") - end - cmd(string.format("rm -rf %s %s /tmp/etc/%s.include", CONFIG_PATH, LOG_APP_FILE, CONFIG)) + cmd(string.format("/bin/busybox top -bn1 | grep -v 'grep' | grep '%s/' | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1", CONFIG_PATH)) + if nft_flag == "0" then + ipt("-D INPUT -j PSW-SERVER 2>/dev/null") + ipt("-F PSW-SERVER 2>/dev/null") + ipt("-X PSW-SERVER 2>/dev/null") + ip6t("-D INPUT -j PSW-SERVER 2>/dev/null") + ip6t("-F PSW-SERVER 2>/dev/null") + ip6t("-X PSW-SERVER 2>/dev/null") + else + nft_cmd="handles=$(nft -a list chain inet fw4 input | grep -E \"PSW-SERVER\" | awk -F '# handle ' '{print$2}')\n for handle in $handles; do\n nft delete rule inet fw4 input handle ${handle} 2>/dev/null\n done" + cmd(nft_cmd) + cmd("nft flush chain inet fw4 PSW-SERVER 2>/dev/null") + cmd("nft delete chain inet fw4 PSW-SERVER 2>/dev/null") + end + cmd(string.format("rm -rf %s %s /tmp/etc/%s.include", CONFIG_PATH, LOG_APP_FILE, CONFIG)) end if action then - if action == "start" then - start() - elseif action == "stop" then - stop() - end + if action == "start" then + start() + elseif action == "stop" then + stop() + end end diff --git a/luci-app-passwall/luasrc/passwall/util_hysteria.lua b/luci-app-passwall/luasrc/passwall/util_hysteria.lua index 9769a009f..9212147c7 100644 --- a/luci-app-passwall/luasrc/passwall/util_hysteria.lua +++ b/luci-app-passwall/luasrc/passwall/util_hysteria.lua @@ -4,116 +4,115 @@ local uci = api.uci local jsonc = api.jsonc function gen_config_server(node) - local config = { - listen = ":" .. node.port, - protocol = node.protocol or "udp", - obfs = node.hysteria_obfs, - cert = node.tls_certificateFile, - key = node.tls_keyFile, - auth = (node.hysteria_auth_type == "string") and { - mode = "password", - config = { - password = node.hysteria_auth_password - } - } or nil, - disable_udp = (node.hysteria_udp == "0") and true or false, - alpn = node.hysteria_alpn or nil, - up_mbps = tonumber(node.hysteria_up_mbps) or 10, - down_mbps = tonumber(node.hysteria_down_mbps) or 50, - recv_window_conn = (node.hysteria_recv_window_conn) and tonumber(node.hysteria_recv_window_conn) or nil, - recv_window = (node.hysteria_recv_window) and tonumber(node.hysteria_recv_window) or nil, - disable_mtu_discovery = (node.hysteria_disable_mtu_discovery) and true or false - } - return config + local config = { + listen = ":" .. node.port, + protocol = node.protocol or "udp", + obfs = node.hysteria_obfs, + cert = node.tls_certificateFile, + key = node.tls_keyFile, + auth = (node.hysteria_auth_type == "string") and { + mode = "password", + config = { + password = node.hysteria_auth_password + } + } or nil, + disable_udp = (node.hysteria_udp == "0") and true or false, + alpn = node.hysteria_alpn or nil, + up_mbps = tonumber(node.hysteria_up_mbps) or 10, + down_mbps = tonumber(node.hysteria_down_mbps) or 50, + recv_window_conn = (node.hysteria_recv_window_conn) and tonumber(node.hysteria_recv_window_conn) or nil, + recv_window = (node.hysteria_recv_window) and tonumber(node.hysteria_recv_window) or nil, + disable_mtu_discovery = (node.hysteria_disable_mtu_discovery) and true or false + } + return config end - function gen_config(var) - local node_id = var["-node"] - if not node_id then - print("-node 不能为空") - return - end - local node = uci:get_all("passwall", node_id) - local local_tcp_redir_port = var["-local_tcp_redir_port"] - local local_udp_redir_port = var["-local_udp_redir_port"] - local local_socks_address = var["-local_socks_address"] or "0.0.0.0" - local local_socks_port = var["-local_socks_port"] - local local_socks_username = var["-local_socks_username"] - local local_socks_password = var["-local_socks_password"] - local local_http_address = var["-local_http_address"] or "0.0.0.0" - local local_http_port = var["-local_http_port"] - local local_http_username = var["-local_http_username"] - local local_http_password = var["-local_http_password"] - local tcp_proxy_way = var["-tcp_proxy_way"] - local server_host = var["-server_host"] or node.address - local server_port = var["-server_port"] or node.port + local node_id = var["-node"] + if not node_id then + print("-node 不能为空") + return + end + local node = uci:get_all("passwall", node_id) + local local_tcp_redir_port = var["-local_tcp_redir_port"] + local local_udp_redir_port = var["-local_udp_redir_port"] + local local_socks_address = var["-local_socks_address"] or "0.0.0.0" + local local_socks_port = var["-local_socks_port"] + local local_socks_username = var["-local_socks_username"] + local local_socks_password = var["-local_socks_password"] + local local_http_address = var["-local_http_address"] or "0.0.0.0" + local local_http_port = var["-local_http_port"] + local local_http_username = var["-local_http_username"] + local local_http_password = var["-local_http_password"] + local tcp_proxy_way = var["-tcp_proxy_way"] + local server_host = var["-server_host"] or node.address + local server_port = var["-server_port"] or node.port - if api.is_ipv6(server_host) then - server_host = api.get_ipv6_full(server_host) - end - local server = server_host .. ":" .. server_port + if api.is_ipv6(server_host) then + server_host = api.get_ipv6_full(server_host) + end + local server = server_host .. ":" .. server_port - if (node.hysteria_hop) then - server = server .. "," .. node.hysteria_hop - end + if (node.hysteria_hop) then + server = server .. "," .. node.hysteria_hop + end - local config = { - server = server, - protocol = node.protocol or "udp", - obfs = node.hysteria_obfs, - auth = (node.hysteria_auth_type == "base64") and node.hysteria_auth_password or nil, - auth_str = (node.hysteria_auth_type == "string") and node.hysteria_auth_password or nil, - alpn = node.hysteria_alpn or nil, - server_name = node.tls_serverName, - insecure = (node.tls_allowInsecure == "1") and true or false, - up_mbps = tonumber(node.hysteria_up_mbps) or 10, - down_mbps = tonumber(node.hysteria_down_mbps) or 50, - retry = -1, - retry_interval = 5, - recv_window_conn = (node.hysteria_recv_window_conn) and tonumber(node.hysteria_recv_window_conn) or nil, - recv_window = (node.hysteria_recv_window) and tonumber(node.hysteria_recv_window) or nil, - handshake_timeout = (node.hysteria_handshake_timeout) and tonumber(node.hysteria_handshake_timeout) or nil, - idle_timeout = (node.hysteria_idle_timeout) and tonumber(node.hysteria_idle_timeout) or nil, - hop_interval = (node.hysteria_hop_interval) and tonumber(node.hysteria_hop_interval) or nil, - disable_mtu_discovery = (node.hysteria_disable_mtu_discovery) and true or false, - fast_open = (node.fast_open == "1") and true or false, - socks5 = (local_socks_address and local_socks_port) and { - listen = local_socks_address .. ":" .. local_socks_port, - timeout = 300, - disable_udp = false, - user = (local_socks_username and local_socks_password) and local_socks_username, - password = (local_socks_username and local_socks_password) and local_socks_password, - } or nil, - http = (local_http_address and local_http_port) and { - listen = local_http_address .. ":" .. local_http_port, - timeout = 300, - disable_udp = false, - user = (local_http_username and local_http_password) and local_http_username, - password = (local_http_username and local_http_password) and local_http_password, - } or nil, - redirect_tcp = ("redirect" == tcp_proxy_way and local_tcp_redir_port) and { - listen = "0.0.0.0:" .. local_tcp_redir_port, - timeout = 300 - } or nil, - tproxy_tcp = ("tproxy" == tcp_proxy_way and local_tcp_redir_port) and { - listen = "0.0.0.0:" .. local_tcp_redir_port, - timeout = 300 - } or nil, - tproxy_udp = (local_udp_redir_port) and { - listen = "0.0.0.0:" .. local_udp_redir_port, - timeout = 60 - } or nil - } + local config = { + server = server, + protocol = node.protocol or "udp", + obfs = node.hysteria_obfs, + auth = (node.hysteria_auth_type == "base64") and node.hysteria_auth_password or nil, + auth_str = (node.hysteria_auth_type == "string") and node.hysteria_auth_password or nil, + alpn = node.hysteria_alpn or nil, + server_name = node.tls_serverName, + insecure = (node.tls_allowInsecure == "1") and true or false, + up_mbps = tonumber(node.hysteria_up_mbps) or 10, + down_mbps = tonumber(node.hysteria_down_mbps) or 50, + retry = -1, + retry_interval = 5, + recv_window_conn = (node.hysteria_recv_window_conn) and tonumber(node.hysteria_recv_window_conn) or nil, + recv_window = (node.hysteria_recv_window) and tonumber(node.hysteria_recv_window) or nil, + handshake_timeout = (node.hysteria_handshake_timeout) and tonumber(node.hysteria_handshake_timeout) or nil, + idle_timeout = (node.hysteria_idle_timeout) and tonumber(node.hysteria_idle_timeout) or nil, + hop_interval = (node.hysteria_hop_interval) and tonumber(node.hysteria_hop_interval) or nil, + disable_mtu_discovery = (node.hysteria_disable_mtu_discovery) and true or false, + fast_open = (node.fast_open == "1") and true or false, + socks5 = (local_socks_address and local_socks_port) and { + listen = local_socks_address .. ":" .. local_socks_port, + timeout = 300, + disable_udp = false, + user = (local_socks_username and local_socks_password) and local_socks_username, + password = (local_socks_username and local_socks_password) and local_socks_password, + } or nil, + http = (local_http_address and local_http_port) and { + listen = local_http_address .. ":" .. local_http_port, + timeout = 300, + disable_udp = false, + user = (local_http_username and local_http_password) and local_http_username, + password = (local_http_username and local_http_password) and local_http_password, + } or nil, + redirect_tcp = ("redirect" == tcp_proxy_way and local_tcp_redir_port) and { + listen = "0.0.0.0:" .. local_tcp_redir_port, + timeout = 300 + } or nil, + tproxy_tcp = ("tproxy" == tcp_proxy_way and local_tcp_redir_port) and { + listen = "0.0.0.0:" .. local_tcp_redir_port, + timeout = 300 + } or nil, + tproxy_udp = (local_udp_redir_port) and { + listen = "0.0.0.0:" .. local_udp_redir_port, + timeout = 60 + } or nil + } - return jsonc.stringify(config, 1) + return jsonc.stringify(config, 1) end _G.gen_config = gen_config if arg[1] then - local func =_G[arg[1]] - if func then - print(func(api.get_function_args(arg))) - end + local func =_G[arg[1]] + if func then + print(func(api.get_function_args(arg))) + end end diff --git a/luci-app-passwall/luasrc/passwall/util_naiveproxy.lua b/luci-app-passwall/luasrc/passwall/util_naiveproxy.lua index 91c78347c..ee095c1e6 100644 --- a/luci-app-passwall/luasrc/passwall/util_naiveproxy.lua +++ b/luci-app-passwall/luasrc/passwall/util_naiveproxy.lua @@ -4,36 +4,36 @@ local uci = api.uci local jsonc = api.jsonc function gen_config(var) - local node_id = var["-node"] - if not node_id then - print("-node 不能为空") - return - end - local node = uci:get_all("passwall", node_id) - local run_type = var["-run_type"] - local local_addr = var["-local_addr"] - local local_port = var["-local_port"] - local server_host = var["-server_host"] or node.address - local server_port = var["-server_port"] or node.port + local node_id = var["-node"] + if not node_id then + print("-node 不能为空") + return + end + local node = uci:get_all("passwall", node_id) + local run_type = var["-run_type"] + local local_addr = var["-local_addr"] + local local_port = var["-local_port"] + local server_host = var["-server_host"] or node.address + local server_port = var["-server_port"] or node.port - if api.is_ipv6(server_host) then - server_host = api.get_ipv6_full(server_host) - end - local server = server_host .. ":" .. server_port + if api.is_ipv6(server_host) then + server_host = api.get_ipv6_full(server_host) + end + local server = server_host .. ":" .. server_port - local config = { - listen = run_type .. "://" .. local_addr .. ":" .. local_port, - proxy = node.protocol .. "://" .. node.username .. ":" .. node.password .. "@" .. server - } + local config = { + listen = run_type .. "://" .. local_addr .. ":" .. local_port, + proxy = node.protocol .. "://" .. node.username .. ":" .. node.password .. "@" .. server + } - return jsonc.stringify(config, 1) + return jsonc.stringify(config, 1) end _G.gen_config = gen_config if arg[1] then - local func =_G[arg[1]] - if func then - print(func(api.get_function_args(arg))) - end + local func =_G[arg[1]] + if func then + print(func(api.get_function_args(arg))) + end end diff --git a/luci-app-passwall/luasrc/passwall/util_shadowsocks.lua b/luci-app-passwall/luasrc/passwall/util_shadowsocks.lua index 78673e35f..e6080001b 100644 --- a/luci-app-passwall/luasrc/passwall/util_shadowsocks.lua +++ b/luci-app-passwall/luasrc/passwall/util_shadowsocks.lua @@ -4,141 +4,141 @@ local uci = api.uci local jsonc = api.jsonc function gen_config_server(node) - local config = {} - config.server_port = tonumber(node.port) - config.password = node.password - config.timeout = tonumber(node.timeout) - config.fast_open = (node.tcp_fast_open and node.tcp_fast_open == "1") and true or false - config.method = node.method + local config = {} + config.server_port = tonumber(node.port) + config.password = node.password + config.timeout = tonumber(node.timeout) + config.fast_open = (node.tcp_fast_open and node.tcp_fast_open == "1") and true or false + config.method = node.method - if node.type == "SS-Rust" then - config.server = "::" - config.mode = "tcp_and_udp" - else - config.server = {"[::0]", "0.0.0.0"} - end + if node.type == "SS-Rust" then + config.server = "::" + config.mode = "tcp_and_udp" + else + config.server = {"[::0]", "0.0.0.0"} + end - if node.type == "SSR" then - config.protocol = node.protocol - config.protocol_param = node.protocol_param - config.obfs = node.obfs - config.obfs_param = node.obfs_param - end + if node.type == "SSR" then + config.protocol = node.protocol + config.protocol_param = node.protocol_param + config.obfs = node.obfs + config.obfs_param = node.obfs_param + end - return config + return config end function gen_config(var) - local node_id = var["-node"] - if not node_id then - print("-node 不能为空") - return - end - local node = uci:get_all("passwall", node_id) - local server_host = var["-server_host"] or node.address - local server_port = var["-server_port"] or node.port - local local_addr = var["-local_addr"] - local local_port = var["-local_port"] - local mode = var["-mode"] - local local_socks_address = var["-local_socks_address"] or "0.0.0.0" - local local_socks_port = var["-local_socks_port"] - local local_socks_username = var["-local_socks_username"] - local local_socks_password = var["-local_socks_password"] - local local_http_address = var["-local_http_address"] or "0.0.0.0" - local local_http_port = var["-local_http_port"] - local local_http_username = var["-local_http_username"] - local local_http_password = var["-local_http_password"] - local local_tcp_redir_port = var["-local_tcp_redir_port"] - local local_tcp_redir_address = var["-local_tcp_redir_address"] or "0.0.0.0" - local local_udp_redir_port = var["-local_udp_redir_port"] - local local_udp_redir_address = var["-local_udp_redir_address"] or "0.0.0.0" + local node_id = var["-node"] + if not node_id then + print("-node 不能为空") + return + end + local node = uci:get_all("passwall", node_id) + local server_host = var["-server_host"] or node.address + local server_port = var["-server_port"] or node.port + local local_addr = var["-local_addr"] + local local_port = var["-local_port"] + local mode = var["-mode"] + local local_socks_address = var["-local_socks_address"] or "0.0.0.0" + local local_socks_port = var["-local_socks_port"] + local local_socks_username = var["-local_socks_username"] + local local_socks_password = var["-local_socks_password"] + local local_http_address = var["-local_http_address"] or "0.0.0.0" + local local_http_port = var["-local_http_port"] + local local_http_username = var["-local_http_username"] + local local_http_password = var["-local_http_password"] + local local_tcp_redir_port = var["-local_tcp_redir_port"] + local local_tcp_redir_address = var["-local_tcp_redir_address"] or "0.0.0.0" + local local_udp_redir_port = var["-local_udp_redir_port"] + local local_udp_redir_address = var["-local_udp_redir_address"] or "0.0.0.0" - if api.is_ipv6(server_host) then - server_host = api.get_ipv6_only(server_host) - end - local server = server_host + if api.is_ipv6(server_host) then + server_host = api.get_ipv6_only(server_host) + end + local server = server_host - local config = { - server = server, - server_port = tonumber(server_port), - local_address = local_addr, - local_port = tonumber(local_port), - password = node.password, - method = node.method, - timeout = tonumber(node.timeout), - fast_open = (node.tcp_fast_open and node.tcp_fast_open == "true") and true or false, - reuse_port = true, - tcp_tproxy = var["-tcp_tproxy"] and true or nil - } + local config = { + server = server, + server_port = tonumber(server_port), + local_address = local_addr, + local_port = tonumber(local_port), + password = node.password, + method = node.method, + timeout = tonumber(node.timeout), + fast_open = (node.tcp_fast_open and node.tcp_fast_open == "true") and true or false, + reuse_port = true, + tcp_tproxy = var["-tcp_tproxy"] and true or nil + } - if node.type == "SS" then - if node.plugin and node.plugin ~= "none" then - config.plugin = node.plugin - config.plugin_opts = node.plugin_opts or nil - end - config.mode = mode - elseif node.type == "SSR" then - config.protocol = node.protocol - config.protocol_param = node.protocol_param - config.obfs = node.obfs - config.obfs_param = node.obfs_param - elseif node.type == "SS-Rust" then - config = { - servers = { - { - address = server, - port = tonumber(server_port), - method = node.method, - password = node.password, - timeout = tonumber(node.timeout), - plugin = (node.plugin and node.plugin ~= "none") and node.plugin or nil, - plugin_opts = (node.plugin and node.plugin ~= "none") and node.plugin_opts or nil - } - }, - locals = {}, - fast_open = (node.tcp_fast_open and node.tcp_fast_open == "true") and true or false - } - if local_socks_address and local_socks_port then - table.insert(config.locals, { - local_address = local_socks_address, - local_port = tonumber(local_socks_port), - mode = "tcp_and_udp" - }) - end - if local_http_address and local_http_port then - table.insert(config.locals, { - protocol = "http", - local_address = local_http_address, - local_port = tonumber(local_http_port) - }) - end - if local_tcp_redir_address and local_tcp_redir_port then - table.insert(config.locals, { - protocol = "redir", - mode = "tcp_only", - tcp_redir = var["-tcp_tproxy"] and "tproxy" or nil, - local_address = local_tcp_redir_address, - local_port = tonumber(local_tcp_redir_port) - }) - end - if local_udp_redir_address and local_udp_redir_port then - table.insert(config.locals, { - protocol = "redir", - mode = "udp_only", - local_address = local_udp_redir_address, - local_port = tonumber(local_udp_redir_port) - }) - end - end + if node.type == "SS" then + if node.plugin and node.plugin ~= "none" then + config.plugin = node.plugin + config.plugin_opts = node.plugin_opts or nil + end + config.mode = mode + elseif node.type == "SSR" then + config.protocol = node.protocol + config.protocol_param = node.protocol_param + config.obfs = node.obfs + config.obfs_param = node.obfs_param + elseif node.type == "SS-Rust" then + config = { + servers = { + { + address = server, + port = tonumber(server_port), + method = node.method, + password = node.password, + timeout = tonumber(node.timeout), + plugin = (node.plugin and node.plugin ~= "none") and node.plugin or nil, + plugin_opts = (node.plugin and node.plugin ~= "none") and node.plugin_opts or nil + } + }, + locals = {}, + fast_open = (node.tcp_fast_open and node.tcp_fast_open == "true") and true or false + } + if local_socks_address and local_socks_port then + table.insert(config.locals, { + local_address = local_socks_address, + local_port = tonumber(local_socks_port), + mode = "tcp_and_udp" + }) + end + if local_http_address and local_http_port then + table.insert(config.locals, { + protocol = "http", + local_address = local_http_address, + local_port = tonumber(local_http_port) + }) + end + if local_tcp_redir_address and local_tcp_redir_port then + table.insert(config.locals, { + protocol = "redir", + mode = "tcp_only", + tcp_redir = var["-tcp_tproxy"] and "tproxy" or nil, + local_address = local_tcp_redir_address, + local_port = tonumber(local_tcp_redir_port) + }) + end + if local_udp_redir_address and local_udp_redir_port then + table.insert(config.locals, { + protocol = "redir", + mode = "udp_only", + local_address = local_udp_redir_address, + local_port = tonumber(local_udp_redir_port) + }) + end + end - return jsonc.stringify(config, 1) + return jsonc.stringify(config, 1) end _G.gen_config = gen_config if arg[1] then - local func =_G[arg[1]] - if func then - print(func(api.get_function_args(arg))) - end + local func =_G[arg[1]] + if func then + print(func(api.get_function_args(arg))) + end end diff --git a/luci-app-passwall/luasrc/passwall/util_trojan.lua b/luci-app-passwall/luasrc/passwall/util_trojan.lua index 33814d279..9961e8180 100644 --- a/luci-app-passwall/luasrc/passwall/util_trojan.lua +++ b/luci-app-passwall/luasrc/passwall/util_trojan.lua @@ -4,155 +4,155 @@ local uci = api.uci local json = api.jsonc function gen_config_server(node) - local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA" - local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384" - local config = { - run_type = "server", - local_addr = "::", - local_port = tonumber(node.port), - remote_addr = (node.remote_enable == "1" and node.remote_address) and node.remote_address or nil, - remote_port = (node.remote_enable == "1" and node.remote_port) and tonumber(node.remote_port) or nil, - password = node.uuid, - log_level = (node.log and node.log == "1") and tonumber(node.loglevel) or 5, - ssl = { - cert = node.tls_certificateFile, - key = node.tls_keyFile, - key_password = "", - cipher = cipher, - cipher_tls13 = cipher13, - prefer_server_cipher = true, - reuse_session = true, - session_ticket = (node.tls_sessionTicket == "1") and true or false, - session_timeout = 600, - plain_http_response = "", - curves = "", - dhparam = "" - }, - tcp = { - prefer_ipv4 = false, - no_delay = true, - keep_alive = true, - reuse_port = false, - fast_open = (node.tcp_fast_open and node.tcp_fast_open == "1") and true or false, - fast_open_qlen = 20 - } - } - if node.type == "Trojan-Go" then - config.ssl.cipher = nil - config.ssl.cipher_tls13 = nil - config.udp_timeout = 60 - config.disable_http_check = true - config.transport_plugin = ((node.tls == nil or node.tls ~= "1") and node.trojan_transport == "original") and { - enabled = node.plugin_type ~= nil, - type = node.plugin_type or "plaintext", - command = node.plugin_type ~= "plaintext" and node.plugin_cmd or nil, - option = node.plugin_type ~= "plaintext" and node.plugin_option or nil, - arg = node.plugin_type ~= "plaintext" and { node.plugin_arg } or nil, - env = {} - } or nil - config.websocket = (node.trojan_transport == 'ws') and { - enabled = true, - path = node.ws_path or "/", - host = node.ws_host or "" - } or nil - config.shadowsocks = (node.ss_aead == "1") and { - enabled = true, - method = node.ss_aead_method or "aes_128_gcm", - password = node.ss_aead_pwd or "" - } or nil - end - return config + local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA" + local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384" + local config = { + run_type = "server", + local_addr = "::", + local_port = tonumber(node.port), + remote_addr = (node.remote_enable == "1" and node.remote_address) and node.remote_address or nil, + remote_port = (node.remote_enable == "1" and node.remote_port) and tonumber(node.remote_port) or nil, + password = node.uuid, + log_level = (node.log and node.log == "1") and tonumber(node.loglevel) or 5, + ssl = { + cert = node.tls_certificateFile, + key = node.tls_keyFile, + key_password = "", + cipher = cipher, + cipher_tls13 = cipher13, + prefer_server_cipher = true, + reuse_session = true, + session_ticket = (node.tls_sessionTicket == "1") and true or false, + session_timeout = 600, + plain_http_response = "", + curves = "", + dhparam = "" + }, + tcp = { + prefer_ipv4 = false, + no_delay = true, + keep_alive = true, + reuse_port = false, + fast_open = (node.tcp_fast_open and node.tcp_fast_open == "1") and true or false, + fast_open_qlen = 20 + } + } + if node.type == "Trojan-Go" then + config.ssl.cipher = nil + config.ssl.cipher_tls13 = nil + config.udp_timeout = 60 + config.disable_http_check = true + config.transport_plugin = ((node.tls == nil or node.tls ~= "1") and node.trojan_transport == "original") and { + enabled = node.plugin_type ~= nil, + type = node.plugin_type or "plaintext", + command = node.plugin_type ~= "plaintext" and node.plugin_cmd or nil, + option = node.plugin_type ~= "plaintext" and node.plugin_option or nil, + arg = node.plugin_type ~= "plaintext" and { node.plugin_arg } or nil, + env = {} + } or nil + config.websocket = (node.trojan_transport == 'ws') and { + enabled = true, + path = node.ws_path or "/", + host = node.ws_host or "" + } or nil + config.shadowsocks = (node.ss_aead == "1") and { + enabled = true, + method = node.ss_aead_method or "aes_128_gcm", + password = node.ss_aead_pwd or "" + } or nil + end + return config end function gen_config(var) - local node_id = var["-node"] - if not node_id then - print("-node 不能为空") - return - end - local node = uci:get_all("passwall", node_id) - local run_type = var["-run_type"] - local local_addr = var["-local_addr"] - local local_port = var["-local_port"] - local server_host = var["-server_host"] or node.address - local server_port = var["-server_port"] or node.port - local loglevel = var["-loglevel"] or 2 - local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA" - local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384" + local node_id = var["-node"] + if not node_id then + print("-node 不能为空") + return + end + local node = uci:get_all("passwall", node_id) + local run_type = var["-run_type"] + local local_addr = var["-local_addr"] + local local_port = var["-local_port"] + local server_host = var["-server_host"] or node.address + local server_port = var["-server_port"] or node.port + local loglevel = var["-loglevel"] or 2 + local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA" + local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384" - if api.is_ipv6(server_host) then - server_host = api.get_ipv6_only(server_host) - end - local server = server_host + if api.is_ipv6(server_host) then + server_host = api.get_ipv6_only(server_host) + end + local server = server_host - local trojan = { - run_type = run_type, - local_addr = local_addr, - local_port = tonumber(local_port), - remote_addr = server, - remote_port = tonumber(server_port), - password = {node.password}, - log_level = tonumber(loglevel), - ssl = { - verify = (node.tls_allowInsecure ~= "1") and true or false, - verify_hostname = true, - cert = nil, - cipher = cipher, - cipher_tls13 = cipher13, - sni = node.tls_serverName or server, - alpn = {"h2", "http/1.1"}, - reuse_session = true, - session_ticket = (node.tls_sessionTicket and node.tls_sessionTicket == "1") and true or false, - curves = "" - }, - udp_timeout = 60, - tcp = { - use_tproxy = (node.type == "Trojan-Plus" and var["-use_tproxy"]) and true or nil, - no_delay = true, - keep_alive = true, - reuse_port = true, - fast_open = (node.tcp_fast_open == "true") and true or false, - fast_open_qlen = 20 - } - } - if node.type == "Trojan-Go" then - trojan.ssl.cipher = nil - trojan.ssl.cipher_tls13 = nil - trojan.ssl.fingerprint = (node.fingerprint ~= "disable") and node.fingerprint or "" - trojan.ssl.alpn = (node.trojan_transport == 'ws') and {} or {"h2", "http/1.1"} - if node.tls ~= "1" and node.trojan_transport == "original" then trojan.ssl = nil end - trojan.transport_plugin = ((not node.tls or node.tls ~= "1") and node.trojan_transport == "original") and { - enabled = node.plugin_type ~= nil, - type = node.plugin_type or "plaintext", - command = node.plugin_type ~= "plaintext" and node.plugin_cmd or nil, - option = node.plugin_type ~= "plaintext" and node.plugin_option or nil, - arg = node.plugin_type ~= "plaintext" and { node.plugin_arg } or nil, - env = {} - } or nil - trojan.websocket = (node.trojan_transport == 'ws') and { - enabled = true, - path = node.ws_path or "/", - host = node.ws_host or (node.tls_serverName or server) - } or nil - trojan.shadowsocks = (node.ss_aead == "1") and { - enabled = true, - method = node.ss_aead_method or "aes_128_gcm", - password = node.ss_aead_pwd or "" - } or nil - trojan.mux = (node.smux == "1") and { - enabled = true, - concurrency = tonumber(node.mux_concurrency), - idle_timeout = tonumber(node.smux_idle_timeout) - } or nil - end - return json.stringify(trojan, 1) + local trojan = { + run_type = run_type, + local_addr = local_addr, + local_port = tonumber(local_port), + remote_addr = server, + remote_port = tonumber(server_port), + password = {node.password}, + log_level = tonumber(loglevel), + ssl = { + verify = (node.tls_allowInsecure ~= "1") and true or false, + verify_hostname = true, + cert = nil, + cipher = cipher, + cipher_tls13 = cipher13, + sni = node.tls_serverName or server, + alpn = {"h2", "http/1.1"}, + reuse_session = true, + session_ticket = (node.tls_sessionTicket and node.tls_sessionTicket == "1") and true or false, + curves = "" + }, + udp_timeout = 60, + tcp = { + use_tproxy = (node.type == "Trojan-Plus" and var["-use_tproxy"]) and true or nil, + no_delay = true, + keep_alive = true, + reuse_port = true, + fast_open = (node.tcp_fast_open == "true") and true or false, + fast_open_qlen = 20 + } + } + if node.type == "Trojan-Go" then + trojan.ssl.cipher = nil + trojan.ssl.cipher_tls13 = nil + trojan.ssl.fingerprint = (node.fingerprint ~= "disable") and node.fingerprint or "" + trojan.ssl.alpn = (node.trojan_transport == 'ws') and {} or {"h2", "http/1.1"} + if node.tls ~= "1" and node.trojan_transport == "original" then trojan.ssl = nil end + trojan.transport_plugin = ((not node.tls or node.tls ~= "1") and node.trojan_transport == "original") and { + enabled = node.plugin_type ~= nil, + type = node.plugin_type or "plaintext", + command = node.plugin_type ~= "plaintext" and node.plugin_cmd or nil, + option = node.plugin_type ~= "plaintext" and node.plugin_option or nil, + arg = node.plugin_type ~= "plaintext" and { node.plugin_arg } or nil, + env = {} + } or nil + trojan.websocket = (node.trojan_transport == 'ws') and { + enabled = true, + path = node.ws_path or "/", + host = node.ws_host or (node.tls_serverName or server) + } or nil + trojan.shadowsocks = (node.ss_aead == "1") and { + enabled = true, + method = node.ss_aead_method or "aes_128_gcm", + password = node.ss_aead_pwd or "" + } or nil + trojan.mux = (node.smux == "1") and { + enabled = true, + concurrency = tonumber(node.mux_concurrency), + idle_timeout = tonumber(node.smux_idle_timeout) + } or nil + end + return json.stringify(trojan, 1) end _G.gen_config = gen_config if arg[1] then - local func =_G[arg[1]] - if func then - print(func(api.get_function_args(arg))) - end + local func =_G[arg[1]] + if func then + print(func(api.get_function_args(arg))) + end end diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index 2e79db161..bacdcb5d3 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -9,1188 +9,1188 @@ local fs = api.fs local new_port local function get_new_port() - if new_port then - new_port = tonumber(sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port %s tcp)", appname, new_port + 1))) - else - new_port = tonumber(sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port auto tcp)", appname))) - end - return new_port + if new_port then + new_port = tonumber(sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port %s tcp)", appname, new_port + 1))) + else + new_port = tonumber(sys.exec(string.format("echo -n $(/usr/share/%s/app.sh get_new_port auto tcp)", appname))) + end + return new_port end local function get_domain_excluded() - local path = string.format("/usr/share/%s/rules/domains_excluded", appname) - local content = fs.readfile(path) - if not content then return nil end - local hosts = {} - string.gsub(content, '[^' .. "\n" .. ']+', function(w) - local s = w:gsub("^%s*(.-)%s*$", "%1") -- Trim - if s == "" then return end - if s:find("#") and s:find("#") == 1 then return end - if not s:find("#") or s:find("#") ~= 1 then table.insert(hosts, s) end - end) - if #hosts == 0 then hosts = nil end - return hosts + local path = string.format("/usr/share/%s/rules/domains_excluded", appname) + local content = fs.readfile(path) + if not content then return nil end + local hosts = {} + string.gsub(content, '[^' .. "\n" .. ']+', function(w) + local s = w:gsub("^%s*(.-)%s*$", "%1") -- Trim + if s == "" then return end + if s:find("#") and s:find("#") == 1 then return end + if not s:find("#") or s:find("#") ~= 1 then table.insert(hosts, s) end + end) + if #hosts == 0 then hosts = nil end + return hosts end function gen_outbound(flag, node, tag, proxy_table) - local result = nil - if node and node ~= "nil" then - local node_id = node[".name"] - if tag == nil then - tag = node_id - end + local result = nil + if node and node ~= "nil" then + local node_id = node[".name"] + if tag == nil then + tag = node_id + end - local proxy = 0 - local proxy_tag = "nil" - local dialerProxy = nil - if proxy_table ~= nil and type(proxy_table) == "table" then - proxy = proxy_table.proxy or 0 - proxy_tag = proxy_table.tag or "nil" - dialerProxy = proxy_table.dialerProxy - end + local proxy = 0 + local proxy_tag = "nil" + local dialerProxy = nil + if proxy_table ~= nil and type(proxy_table) == "table" then + proxy = proxy_table.proxy or 0 + proxy_tag = proxy_table.tag or "nil" + dialerProxy = proxy_table.dialerProxy + end - if node.type == "V2ray" or node.type == "Xray" then - if node.type == "Xray" and node.tlsflow == "xtls-rprx-vision" then - else - proxy = 0 - if proxy_tag ~= "nil" then - if dialerProxy and dialerProxy == "1" then - node.streamSettings = { - sockopt = { - dialerProxy = proxy_tag - } - } - else - node.proxySettings = { - tag = proxy_tag, - transportLayer = true - } - end - end - end - end + if node.type == "V2ray" or node.type == "Xray" then + if node.type == "Xray" and node.tlsflow == "xtls-rprx-vision" then + else + proxy = 0 + if proxy_tag ~= "nil" then + if dialerProxy and dialerProxy == "1" then + node.streamSettings = { + sockopt = { + dialerProxy = proxy_tag + } + } + else + node.proxySettings = { + tag = proxy_tag, + transportLayer = true + } + end + end + end + end - if node.type ~= "V2ray" and node.type ~= "Xray" then - if node.type == "Socks" then - node.protocol = "socks" - node.transport = "tcp" - else - local relay_port = node.port - new_port = get_new_port() - local config_file = string.format("%s_%s_%s.json", flag, tag, new_port) - if tag and node_id and tag ~= node_id then - config_file = string.format("%s_%s_%s_%s.json", flag, tag, node_id, new_port) - end - sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null', - appname, - string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s relay_port=%s", - new_port, --flag - node_id, --node - "127.0.0.1", --bind - new_port, --socks port - config_file, --config file - (proxy == 1 and relay_port) and tostring(relay_port) or "" --relay port - ) - ) - ) - node = {} - node.protocol = "socks" - node.transport = "tcp" - node.address = "127.0.0.1" - node.port = new_port - end - node.stream_security = "none" - end + if node.type ~= "V2ray" and node.type ~= "Xray" then + if node.type == "Socks" then + node.protocol = "socks" + node.transport = "tcp" + else + local relay_port = node.port + new_port = get_new_port() + local config_file = string.format("%s_%s_%s.json", flag, tag, new_port) + if tag and node_id and tag ~= node_id then + config_file = string.format("%s_%s_%s_%s.json", flag, tag, node_id, new_port) + end + sys.call(string.format('/usr/share/%s/app.sh run_socks "%s"> /dev/null', + appname, + string.format("flag=%s node=%s bind=%s socks_port=%s config_file=%s relay_port=%s", + new_port, --flag + node_id, --node + "127.0.0.1", --bind + new_port, --socks port + config_file, --config file + (proxy == 1 and relay_port) and tostring(relay_port) or "" --relay port + ) + ) + ) + node = {} + node.protocol = "socks" + node.transport = "tcp" + node.address = "127.0.0.1" + node.port = new_port + end + node.stream_security = "none" + end - if node.type == "V2ray" or node.type == "Xray" then - if node.tls and node.tls == "1" then - node.stream_security = "tls" - if node.type == "Xray" and node.reality and node.reality == "1" then - node.stream_security = "reality" - end - end - end + if node.type == "V2ray" or node.type == "Xray" then + if node.tls and node.tls == "1" then + node.stream_security = "tls" + if node.type == "Xray" and node.reality and node.reality == "1" then + node.stream_security = "reality" + end + end + end - result = { - _flag_tag = node_id, - _flag_proxy = proxy, - _flag_proxy_tag = proxy_tag, - tag = tag, - proxySettings = node.proxySettings or nil, - protocol = node.protocol, - mux = { - enabled = (node.mux == "1") and true or false, - concurrency = (node.mux_concurrency) and tonumber(node.mux_concurrency) or 8 - } or nil, - -- 底层传输配置 - streamSettings = (node.streamSettings or node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan") and { - sockopt = { - mark = 255, - dialerProxy = (node.streamSettings and dialerProxy and dialerProxy == "1") and node.streamSettings.sockopt.dialerProxy or nil - }, - network = node.transport, - security = node.stream_security, - tlsSettings = (node.stream_security == "tls") and { - serverName = node.tls_serverName, - allowInsecure = (node.tls_allowInsecure == "1") and true or false, - fingerprint = (node.type == "Xray" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil - } or nil, - realitySettings = (node.stream_security == "reality") and { - serverName = node.tls_serverName, - publicKey = node.reality_publicKey, - shortId = node.reality_shortId or "", - spiderX = node.reality_spiderX or "/", - fingerprint = (node.type == "Xray" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or "chrome" - } or nil, - tcpSettings = (node.transport == "tcp" and node.protocol ~= "socks") and { - header = { - type = node.tcp_guise or "none", - request = (node.tcp_guise == "http") and { - path = node.tcp_guise_http_path or {"/"}, - headers = { - Host = node.tcp_guise_http_host or {} - } - } or nil - } - } or nil, - kcpSettings = (node.transport == "mkcp") and { - mtu = tonumber(node.mkcp_mtu), - tti = tonumber(node.mkcp_tti), - uplinkCapacity = tonumber(node.mkcp_uplinkCapacity), - downlinkCapacity = tonumber(node.mkcp_downlinkCapacity), - congestion = (node.mkcp_congestion == "1") and true or false, - readBufferSize = tonumber(node.mkcp_readBufferSize), - writeBufferSize = tonumber(node.mkcp_writeBufferSize), - seed = (node.mkcp_seed and node.mkcp_seed ~= "") and node.mkcp_seed or nil, - header = {type = node.mkcp_guise} - } or nil, - wsSettings = (node.transport == "ws") and { - path = node.ws_path or "/", - headers = (node.ws_host ~= nil) and - {Host = node.ws_host} or nil, - maxEarlyData = tonumber(node.ws_maxEarlyData) or nil, - earlyDataHeaderName = (node.ws_earlyDataHeaderName) and node.ws_earlyDataHeaderName or nil - } or nil, - httpSettings = (node.transport == "h2") and { - path = node.h2_path or "/", - host = node.h2_host, - read_idle_timeout = tonumber(node.h2_read_idle_timeout) or nil, - health_check_timeout = tonumber(node.h2_health_check_timeout) or nil - } or nil, - dsSettings = (node.transport == "ds") and - {path = node.ds_path} or nil, - quicSettings = (node.transport == "quic") and { - security = node.quic_security, - key = node.quic_key, - header = {type = node.quic_guise} - } or nil, - grpcSettings = (node.transport == "grpc") and { - serviceName = node.grpc_serviceName, - multiMode = (node.grpc_mode == "multi") and true or nil, - idle_timeout = tonumber(node.grpc_idle_timeout) or nil, - health_check_timeout = tonumber(node.grpc_health_check_timeout) or nil, - permit_without_stream = (node.grpc_permit_without_stream == "1") and true or nil, - initial_windows_size = tonumber(node.grpc_initial_windows_size) or nil - } or nil - } or nil, - settings = { - vnext = (node.protocol == "vmess" or node.protocol == "vless") and { - { - address = node.address, - port = tonumber(node.port), - users = { - { - id = node.uuid, - level = 0, - security = (node.protocol == "vmess") and node.security or nil, - encryption = node.encryption or "none", - flow = (node.protocol == "vless" and node.tls == '1' and node.tlsflow) and node.tlsflow or nil - } - } - } - } or nil, - servers = (node.protocol == "socks" or node.protocol == "http" or node.protocol == "shadowsocks" or node.protocol == "trojan") and { - { - address = node.address, - port = tonumber(node.port), - method = node.method 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 "", - users = (node.username and node.password) and { - { - user = node.username, - pass = node.password - } - } or nil - } - } or nil, - address = (node.protocol == "wireguard" and node.wireguard_local_address) and node.wireguard_local_address or nil, - secretKey = (node.protocol == "wireguard") and node.wireguard_secret_key or nil, - peers = (node.protocol == "wireguard") and { - { - publicKey = node.wireguard_public_key, - endpoint = node.address .. ":" .. node.port, - preSharedKey = node.wireguard_preSharedKey, - keepAlive = node.wireguard_keepAlive and tonumber(node.wireguard_keepAlive) or nil - } - } or nil, - mtu = (node.protocol == "wireguard" and node.wireguard_mtu) and tonumber(node.wireguard_mtu) or nil - } - } - local alpn = {} - if node.alpn and node.alpn ~= "default" then - string.gsub(node.alpn, '[^' .. "," .. ']+', function(w) - table.insert(alpn, w) - end) - end - if alpn and #alpn > 0 then - if result.streamSettings.tlsSettings then - result.streamSettings.tlsSettings.alpn = alpn - end - end - end - return result + result = { + _flag_tag = node_id, + _flag_proxy = proxy, + _flag_proxy_tag = proxy_tag, + tag = tag, + proxySettings = node.proxySettings or nil, + protocol = node.protocol, + mux = { + enabled = (node.mux == "1") and true or false, + concurrency = (node.mux_concurrency) and tonumber(node.mux_concurrency) or 8 + } or nil, + -- 底层传输配置 + streamSettings = (node.streamSettings or node.protocol == "vmess" or node.protocol == "vless" or node.protocol == "socks" or node.protocol == "shadowsocks" or node.protocol == "trojan") and { + sockopt = { + mark = 255, + dialerProxy = (node.streamSettings and dialerProxy and dialerProxy == "1") and node.streamSettings.sockopt.dialerProxy or nil + }, + network = node.transport, + security = node.stream_security, + tlsSettings = (node.stream_security == "tls") and { + serverName = node.tls_serverName, + allowInsecure = (node.tls_allowInsecure == "1") and true or false, + fingerprint = (node.type == "Xray" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or nil + } or nil, + realitySettings = (node.stream_security == "reality") and { + serverName = node.tls_serverName, + publicKey = node.reality_publicKey, + shortId = node.reality_shortId or "", + spiderX = node.reality_spiderX or "/", + fingerprint = (node.type == "Xray" and node.fingerprint and node.fingerprint ~= "") and node.fingerprint or "chrome" + } or nil, + tcpSettings = (node.transport == "tcp" and node.protocol ~= "socks") and { + header = { + type = node.tcp_guise or "none", + request = (node.tcp_guise == "http") and { + path = node.tcp_guise_http_path or {"/"}, + headers = { + Host = node.tcp_guise_http_host or {} + } + } or nil + } + } or nil, + kcpSettings = (node.transport == "mkcp") and { + mtu = tonumber(node.mkcp_mtu), + tti = tonumber(node.mkcp_tti), + uplinkCapacity = tonumber(node.mkcp_uplinkCapacity), + downlinkCapacity = tonumber(node.mkcp_downlinkCapacity), + congestion = (node.mkcp_congestion == "1") and true or false, + readBufferSize = tonumber(node.mkcp_readBufferSize), + writeBufferSize = tonumber(node.mkcp_writeBufferSize), + seed = (node.mkcp_seed and node.mkcp_seed ~= "") and node.mkcp_seed or nil, + header = {type = node.mkcp_guise} + } or nil, + wsSettings = (node.transport == "ws") and { + path = node.ws_path or "/", + headers = (node.ws_host ~= nil) and + {Host = node.ws_host} or nil, + maxEarlyData = tonumber(node.ws_maxEarlyData) or nil, + earlyDataHeaderName = (node.ws_earlyDataHeaderName) and node.ws_earlyDataHeaderName or nil + } or nil, + httpSettings = (node.transport == "h2") and { + path = node.h2_path or "/", + host = node.h2_host, + read_idle_timeout = tonumber(node.h2_read_idle_timeout) or nil, + health_check_timeout = tonumber(node.h2_health_check_timeout) or nil + } or nil, + dsSettings = (node.transport == "ds") and + {path = node.ds_path} or nil, + quicSettings = (node.transport == "quic") and { + security = node.quic_security, + key = node.quic_key, + header = {type = node.quic_guise} + } or nil, + grpcSettings = (node.transport == "grpc") and { + serviceName = node.grpc_serviceName, + multiMode = (node.grpc_mode == "multi") and true or nil, + idle_timeout = tonumber(node.grpc_idle_timeout) or nil, + health_check_timeout = tonumber(node.grpc_health_check_timeout) or nil, + permit_without_stream = (node.grpc_permit_without_stream == "1") and true or nil, + initial_windows_size = tonumber(node.grpc_initial_windows_size) or nil + } or nil + } or nil, + settings = { + vnext = (node.protocol == "vmess" or node.protocol == "vless") and { + { + address = node.address, + port = tonumber(node.port), + users = { + { + id = node.uuid, + level = 0, + security = (node.protocol == "vmess") and node.security or nil, + encryption = node.encryption or "none", + flow = (node.protocol == "vless" and node.tls == '1' and node.tlsflow) and node.tlsflow or nil + } + } + } + } or nil, + servers = (node.protocol == "socks" or node.protocol == "http" or node.protocol == "shadowsocks" or node.protocol == "trojan") and { + { + address = node.address, + port = tonumber(node.port), + method = node.method 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 "", + users = (node.username and node.password) and { + { + user = node.username, + pass = node.password + } + } or nil + } + } or nil, + address = (node.protocol == "wireguard" and node.wireguard_local_address) and node.wireguard_local_address or nil, + secretKey = (node.protocol == "wireguard") and node.wireguard_secret_key or nil, + peers = (node.protocol == "wireguard") and { + { + publicKey = node.wireguard_public_key, + endpoint = node.address .. ":" .. node.port, + preSharedKey = node.wireguard_preSharedKey, + keepAlive = node.wireguard_keepAlive and tonumber(node.wireguard_keepAlive) or nil + } + } or nil, + mtu = (node.protocol == "wireguard" and node.wireguard_mtu) and tonumber(node.wireguard_mtu) or nil + } + } + local alpn = {} + if node.alpn and node.alpn ~= "default" then + string.gsub(node.alpn, '[^' .. "," .. ']+', function(w) + table.insert(alpn, w) + end) + end + if alpn and #alpn > 0 then + if result.streamSettings.tlsSettings then + result.streamSettings.tlsSettings.alpn = alpn + end + end + end + return result end function gen_config_server(node) - local settings = nil - local routing = nil - local outbounds = { - {protocol = "freedom", tag = "direct"}, {protocol = "blackhole", tag = "blocked"} - } + local settings = nil + local routing = nil + local outbounds = { + {protocol = "freedom", tag = "direct"}, {protocol = "blackhole", tag = "blocked"} + } - if node.protocol == "vmess" or node.protocol == "vless" then - if node.uuid then - local clients = {} - for i = 1, #node.uuid do - clients[i] = { - id = node.uuid[i], - flow = ("vless" == node.protocol and "1" == node.tls and node.tlsflow) and node.tlsflow or nil - } - end - settings = { - clients = clients, - decryption = node.decryption or "none" - } - end - elseif node.protocol == "socks" then - settings = { - udp = ("1" == node.udp_forward) and true or false, - auth = ("1" == node.auth) and "password" or "noauth", - accounts = ("1" == node.auth) and { - { - user = node.username, - pass = node.password - } - } or nil - } - elseif node.protocol == "http" then - settings = { - allowTransparent = false, - accounts = ("1" == node.auth) and { - { - user = node.username, - pass = node.password - } - } or nil - } - node.transport = "tcp" - node.tcp_guise = "none" - elseif node.protocol == "shadowsocks" then - settings = { - method = node.method, - password = node.password, - ivCheck = ("1" == node.iv_check) and true or false, - network = node.ss_network or "TCP,UDP" - } - elseif node.protocol == "trojan" then - if node.uuid then - local clients = {} - for i = 1, #node.uuid do - clients[i] = { - password = node.uuid[i], - } - end - settings = { - clients = clients - } - end - elseif node.protocol == "mtproto" then - settings = { - users = { - { - secret = (node.password == nil) and "" or node.password - } - } - } - elseif node.protocol == "dokodemo-door" then - settings = { - network = node.d_protocol, - address = node.d_address, - port = tonumber(node.d_port) - } - end + if node.protocol == "vmess" or node.protocol == "vless" then + if node.uuid then + local clients = {} + for i = 1, #node.uuid do + clients[i] = { + id = node.uuid[i], + flow = ("vless" == node.protocol and "1" == node.tls and node.tlsflow) and node.tlsflow or nil + } + end + settings = { + clients = clients, + decryption = node.decryption or "none" + } + end + elseif node.protocol == "socks" then + settings = { + udp = ("1" == node.udp_forward) and true or false, + auth = ("1" == node.auth) and "password" or "noauth", + accounts = ("1" == node.auth) and { + { + user = node.username, + pass = node.password + } + } or nil + } + elseif node.protocol == "http" then + settings = { + allowTransparent = false, + accounts = ("1" == node.auth) and { + { + user = node.username, + pass = node.password + } + } or nil + } + node.transport = "tcp" + node.tcp_guise = "none" + elseif node.protocol == "shadowsocks" then + settings = { + method = node.method, + password = node.password, + ivCheck = ("1" == node.iv_check) and true or false, + network = node.ss_network or "TCP,UDP" + } + elseif node.protocol == "trojan" then + if node.uuid then + local clients = {} + for i = 1, #node.uuid do + clients[i] = { + password = node.uuid[i], + } + end + settings = { + clients = clients + } + end + elseif node.protocol == "mtproto" then + settings = { + users = { + { + secret = (node.password == nil) and "" or node.password + } + } + } + elseif node.protocol == "dokodemo-door" then + settings = { + network = node.d_protocol, + address = node.d_address, + port = tonumber(node.d_port) + } + end - if node.fallback and node.fallback == "1" then - local fallbacks = {} - for i = 1, #node.fallback_list do - local fallbackStr = node.fallback_list[i] - if fallbackStr then - local tmp = {} - string.gsub(fallbackStr, '[^' .. "," .. ']+', function(w) - table.insert(tmp, w) - end) - local dest = tmp[1] or "" - local path = tmp[2] - if dest:find("%.") then - else - dest = tonumber(dest) - end - fallbacks[i] = { - path = path, - dest = dest, - xver = 1 - } - end - end - settings.fallbacks = fallbacks - end + if node.fallback and node.fallback == "1" then + local fallbacks = {} + for i = 1, #node.fallback_list do + local fallbackStr = node.fallback_list[i] + if fallbackStr then + local tmp = {} + string.gsub(fallbackStr, '[^' .. "," .. ']+', function(w) + table.insert(tmp, w) + end) + local dest = tmp[1] or "" + local path = tmp[2] + if dest:find("%.") then + else + dest = tonumber(dest) + end + fallbacks[i] = { + path = path, + dest = dest, + xver = 1 + } + end + end + settings.fallbacks = fallbacks + end - routing = { - domainStrategy = "IPOnDemand", - rules = { - { - type = "field", - ip = {"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"}, - outboundTag = (node.accept_lan == nil or node.accept_lan == "0") and "blocked" or "direct" - } - } - } + routing = { + domainStrategy = "IPOnDemand", + rules = { + { + type = "field", + ip = {"10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"}, + outboundTag = (node.accept_lan == nil or node.accept_lan == "0") and "blocked" or "direct" + } + } + } - if node.outbound_node and node.outbound_node ~= "nil" then - local outbound = nil - if node.outbound_node == "_iface" and node.outbound_node_iface then - outbound = { - protocol = "freedom", - tag = "outbound", - streamSettings = { - sockopt = { - interface = node.outbound_node_iface - } - } - } - else - local outbound_node_t = uci:get_all("passwall", node.outbound_node) - if node.outbound_node == "_socks" or node.outbound_node == "_http" then - outbound_node_t = { - type = node.type, - protocol = node.outbound_node:gsub("_", ""), - transport = "tcp", - address = node.outbound_node_address, - port = node.outbound_node_port, - username = (node.outbound_node_username and node.outbound_node_username ~= "") and node.outbound_node_username or nil, - password = (node.outbound_node_password and node.outbound_node_password ~= "") and node.outbound_node_password or nil, - } - end - outbound = require("luci.passwall.util_xray").gen_outbound(nil, outbound_node_t, "outbound") - end - if outbound then - table.insert(outbounds, 1, outbound) - end - end + if node.outbound_node and node.outbound_node ~= "nil" then + local outbound = nil + if node.outbound_node == "_iface" and node.outbound_node_iface then + outbound = { + protocol = "freedom", + tag = "outbound", + streamSettings = { + sockopt = { + interface = node.outbound_node_iface + } + } + } + else + local outbound_node_t = uci:get_all("passwall", node.outbound_node) + if node.outbound_node == "_socks" or node.outbound_node == "_http" then + outbound_node_t = { + type = node.type, + protocol = node.outbound_node:gsub("_", ""), + transport = "tcp", + address = node.outbound_node_address, + port = node.outbound_node_port, + username = (node.outbound_node_username and node.outbound_node_username ~= "") and node.outbound_node_username or nil, + password = (node.outbound_node_password and node.outbound_node_password ~= "") and node.outbound_node_password or nil, + } + end + outbound = require("luci.passwall.util_xray").gen_outbound(nil, outbound_node_t, "outbound") + end + if outbound then + table.insert(outbounds, 1, outbound) + end + end - local config = { - log = { - -- error = "/tmp/etc/passwall_server/log/" .. user[".name"] .. ".log", - loglevel = ("1" == node.log) and node.loglevel or "none" - }, - -- 传入连接 - inbounds = { - { - listen = (node.bind_local == "1") and "127.0.0.1" or nil, - port = tonumber(node.port), - protocol = node.protocol, - settings = settings, - streamSettings = { - network = node.transport, - security = "none", - tlsSettings = ("1" == node.tls) and { - disableSystemRoot = false, - certificates = { - { - certificateFile = node.tls_certificateFile, - keyFile = node.tls_keyFile - } - } - } or nil, - tcpSettings = (node.transport == "tcp") and { - acceptProxyProtocol = (node.acceptProxyProtocol and node.acceptProxyProtocol == "1") and true or false, - header = { - type = node.tcp_guise, - request = (node.tcp_guise == "http") and { - path = node.tcp_guise_http_path or {"/"}, - headers = { - Host = node.tcp_guise_http_host or {} - } - } or nil - } - } or nil, - kcpSettings = (node.transport == "mkcp") and { - mtu = tonumber(node.mkcp_mtu), - tti = tonumber(node.mkcp_tti), - uplinkCapacity = tonumber(node.mkcp_uplinkCapacity), - downlinkCapacity = tonumber(node.mkcp_downlinkCapacity), - congestion = (node.mkcp_congestion == "1") and true or false, - readBufferSize = tonumber(node.mkcp_readBufferSize), - writeBufferSize = tonumber(node.mkcp_writeBufferSize), - seed = (node.mkcp_seed and node.mkcp_seed ~= "") and node.mkcp_seed or nil, - header = {type = node.mkcp_guise} - } or nil, - wsSettings = (node.transport == "ws") and { - acceptProxyProtocol = (node.acceptProxyProtocol and node.acceptProxyProtocol == "1") and true or false, - headers = (node.ws_host) and {Host = node.ws_host} or nil, - path = node.ws_path - } or nil, - httpSettings = (node.transport == "h2") and { - path = node.h2_path, host = node.h2_host - } or nil, - dsSettings = (node.transport == "ds") and { - path = node.ds_path - } or nil, - quicSettings = (node.transport == "quic") and { - security = node.quic_security, - key = node.quic_key, - header = {type = node.quic_guise} - } or nil, - grpcSettings = (node.transport == "grpc") and { - serviceName = node.grpc_serviceName - } or nil - } - } - }, - -- 传出连接 - outbounds = outbounds, - routing = routing - } + local config = { + log = { + -- error = "/tmp/etc/passwall_server/log/" .. user[".name"] .. ".log", + loglevel = ("1" == node.log) and node.loglevel or "none" + }, + -- 传入连接 + inbounds = { + { + listen = (node.bind_local == "1") and "127.0.0.1" or nil, + port = tonumber(node.port), + protocol = node.protocol, + settings = settings, + streamSettings = { + network = node.transport, + security = "none", + tlsSettings = ("1" == node.tls) and { + disableSystemRoot = false, + certificates = { + { + certificateFile = node.tls_certificateFile, + keyFile = node.tls_keyFile + } + } + } or nil, + tcpSettings = (node.transport == "tcp") and { + acceptProxyProtocol = (node.acceptProxyProtocol and node.acceptProxyProtocol == "1") and true or false, + header = { + type = node.tcp_guise, + request = (node.tcp_guise == "http") and { + path = node.tcp_guise_http_path or {"/"}, + headers = { + Host = node.tcp_guise_http_host or {} + } + } or nil + } + } or nil, + kcpSettings = (node.transport == "mkcp") and { + mtu = tonumber(node.mkcp_mtu), + tti = tonumber(node.mkcp_tti), + uplinkCapacity = tonumber(node.mkcp_uplinkCapacity), + downlinkCapacity = tonumber(node.mkcp_downlinkCapacity), + congestion = (node.mkcp_congestion == "1") and true or false, + readBufferSize = tonumber(node.mkcp_readBufferSize), + writeBufferSize = tonumber(node.mkcp_writeBufferSize), + seed = (node.mkcp_seed and node.mkcp_seed ~= "") and node.mkcp_seed or nil, + header = {type = node.mkcp_guise} + } or nil, + wsSettings = (node.transport == "ws") and { + acceptProxyProtocol = (node.acceptProxyProtocol and node.acceptProxyProtocol == "1") and true or false, + headers = (node.ws_host) and {Host = node.ws_host} or nil, + path = node.ws_path + } or nil, + httpSettings = (node.transport == "h2") and { + path = node.h2_path, host = node.h2_host + } or nil, + dsSettings = (node.transport == "ds") and { + path = node.ds_path + } or nil, + quicSettings = (node.transport == "quic") and { + security = node.quic_security, + key = node.quic_key, + header = {type = node.quic_guise} + } or nil, + grpcSettings = (node.transport == "grpc") and { + serviceName = node.grpc_serviceName + } or nil + } + } + }, + -- 传出连接 + outbounds = outbounds, + routing = routing + } - local alpn = {} - if node.alpn then - string.gsub(node.alpn, '[^' .. "," .. ']+', function(w) - table.insert(alpn, w) - end) - end - if alpn and #alpn > 0 then - if config.inbounds[1].streamSettings.tlsSettings then - config.inbounds[1].streamSettings.tlsSettings.alpn = alpn - end - end + local alpn = {} + if node.alpn then + string.gsub(node.alpn, '[^' .. "," .. ']+', function(w) + table.insert(alpn, w) + end) + end + if alpn and #alpn > 0 then + if config.inbounds[1].streamSettings.tlsSettings then + config.inbounds[1].streamSettings.tlsSettings.alpn = alpn + end + end - if "1" == node.tls then - config.inbounds[1].streamSettings.security = "tls" - end + if "1" == node.tls then + config.inbounds[1].streamSettings.security = "tls" + end - return config + return config end function gen_config(var) - local flag = var["-flag"] - local node_id = var["-node"] - local tcp_proxy_way = var["-tcp_proxy_way"] or "redirect" - local tcp_redir_port = var["-tcp_redir_port"] - local udp_redir_port = var["-udp_redir_port"] - local sniffing = var["-sniffing"] - local route_only = var["-route_only"] - local buffer_size = var["-buffer_size"] - local local_socks_address = var["-local_socks_address"] or "0.0.0.0" - local local_socks_port = var["-local_socks_port"] - local local_socks_username = var["-local_socks_username"] - local local_socks_password = var["-local_socks_password"] - local local_http_address = var["-local_http_address"] or "0.0.0.0" - local local_http_port = var["-local_http_port"] - local local_http_username = var["-local_http_username"] - local local_http_password = var["-local_http_password"] - local dns_listen_port = var["-dns_listen_port"] - local dns_query_strategy = var["-dns_query_strategy"] - local remote_dns_server = var["-remote_dns_server"] - local remote_dns_port = var["-remote_dns_port"] - local remote_dns_tcp_server = var["-remote_dns_tcp_server"] - local remote_dns_doh_url = var["-remote_dns_doh_url"] - local remote_dns_doh_host = var["-remote_dns_doh_host"] - local remote_dns_fake = var["-remote_dns_fake"] - local dns_cache = var["-dns_cache"] - local dns_client_ip = var["-dns_client_ip"] - local dns_socks_address = var["-dns_socks_address"] - local dns_socks_port = var["-dns_socks_port"] - local loglevel = var["-loglevel"] or "warning" + local flag = var["-flag"] + local node_id = var["-node"] + local tcp_proxy_way = var["-tcp_proxy_way"] or "redirect" + local tcp_redir_port = var["-tcp_redir_port"] + local udp_redir_port = var["-udp_redir_port"] + local sniffing = var["-sniffing"] + local route_only = var["-route_only"] + local buffer_size = var["-buffer_size"] + local local_socks_address = var["-local_socks_address"] or "0.0.0.0" + local local_socks_port = var["-local_socks_port"] + local local_socks_username = var["-local_socks_username"] + local local_socks_password = var["-local_socks_password"] + local local_http_address = var["-local_http_address"] or "0.0.0.0" + local local_http_port = var["-local_http_port"] + local local_http_username = var["-local_http_username"] + local local_http_password = var["-local_http_password"] + local dns_listen_port = var["-dns_listen_port"] + local dns_query_strategy = var["-dns_query_strategy"] + local remote_dns_server = var["-remote_dns_server"] + local remote_dns_port = var["-remote_dns_port"] + local remote_dns_tcp_server = var["-remote_dns_tcp_server"] + local remote_dns_doh_url = var["-remote_dns_doh_url"] + local remote_dns_doh_host = var["-remote_dns_doh_host"] + local remote_dns_fake = var["-remote_dns_fake"] + local dns_cache = var["-dns_cache"] + local dns_client_ip = var["-dns_client_ip"] + local dns_socks_address = var["-dns_socks_address"] + local dns_socks_port = var["-dns_socks_port"] + local loglevel = var["-loglevel"] or "warning" - local dns = nil - local fakedns = nil - local routing = nil - local inbounds = {} - local outbounds = {} + local dns = nil + local fakedns = nil + local routing = nil + local inbounds = {} + local outbounds = {} - if node_id then - local node = uci:get_all(appname, node_id) - if local_socks_port then - local inbound = { - listen = local_socks_address, - port = tonumber(local_socks_port), - protocol = "socks", - settings = {auth = "noauth", udp = true}, - sniffing = {enabled = true, destOverride = {"http", "tls"}} - } - if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then - inbound.settings.auth = "password" - inbound.settings.accounts = { - { - user = local_socks_username, - pass = local_socks_password - } - } - end - table.insert(inbounds, inbound) - end - if local_http_port then - local inbound = { - listen = local_http_address, - port = tonumber(local_http_port), - protocol = "http", - settings = {allowTransparent = false} - } - if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then - inbound.settings.accounts = { - { - user = local_http_username, - pass = local_http_password - } - } - end - table.insert(inbounds, inbound) - end + if node_id then + local node = uci:get_all(appname, node_id) + if local_socks_port then + local inbound = { + listen = local_socks_address, + port = tonumber(local_socks_port), + protocol = "socks", + settings = {auth = "noauth", udp = true}, + sniffing = {enabled = true, destOverride = {"http", "tls"}} + } + if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then + inbound.settings.auth = "password" + inbound.settings.accounts = { + { + user = local_socks_username, + pass = local_socks_password + } + } + end + table.insert(inbounds, inbound) + end + if local_http_port then + local inbound = { + listen = local_http_address, + port = tonumber(local_http_port), + protocol = "http", + settings = {allowTransparent = false} + } + if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then + inbound.settings.accounts = { + { + user = local_http_username, + pass = local_http_password + } + } + end + table.insert(inbounds, inbound) + end - if tcp_redir_port or udp_redir_port then - local inbound = { - protocol = "dokodemo-door", - settings = {network = "tcp,udp", followRedirect = true}, - streamSettings = {sockopt = {tproxy = "tproxy"}}, - sniffing = {enabled = sniffing and true or false, destOverride = {"http", "tls", (remote_dns_fake) and "fakedns"}, metadataOnly = false, routeOnly = route_only and true or nil, domainsExcluded = (sniffing and not route_only) and get_domain_excluded() or nil} - } + if tcp_redir_port or udp_redir_port then + local inbound = { + protocol = "dokodemo-door", + settings = {network = "tcp,udp", followRedirect = true}, + streamSettings = {sockopt = {tproxy = "tproxy"}}, + sniffing = {enabled = sniffing and true or false, destOverride = {"http", "tls", (remote_dns_fake) and "fakedns"}, metadataOnly = false, routeOnly = route_only and true or nil, domainsExcluded = (sniffing and not route_only) and get_domain_excluded() or nil} + } - if tcp_redir_port then - local tcp_inbound = api.clone(inbound) - tcp_inbound.tag = "tcp_redir" - tcp_inbound.settings.network = "tcp" - tcp_inbound.port = tonumber(tcp_redir_port) - tcp_inbound.streamSettings.sockopt.tproxy = tcp_proxy_way - table.insert(inbounds, tcp_inbound) - end + if tcp_redir_port then + local tcp_inbound = api.clone(inbound) + tcp_inbound.tag = "tcp_redir" + tcp_inbound.settings.network = "tcp" + tcp_inbound.port = tonumber(tcp_redir_port) + tcp_inbound.streamSettings.sockopt.tproxy = tcp_proxy_way + table.insert(inbounds, tcp_inbound) + end - if udp_redir_port then - local udp_inbound = api.clone(inbound) - udp_inbound.tag = "udp_redir" - udp_inbound.settings.network = "udp" - udp_inbound.port = tonumber(udp_redir_port) - table.insert(inbounds, udp_inbound) - end - end + if udp_redir_port then + local udp_inbound = api.clone(inbound) + udp_inbound.tag = "udp_redir" + udp_inbound.settings.network = "udp" + udp_inbound.port = tonumber(udp_redir_port) + table.insert(inbounds, udp_inbound) + end + end - if node.protocol == "_shunt" then - local rules = {} + if node.protocol == "_shunt" then + local rules = {} - local default_node_id = node.default_node or "_direct" - local default_outboundTag - if default_node_id == "_direct" then - default_outboundTag = "direct" - elseif default_node_id == "_blackhole" then - default_outboundTag = "blackhole" - else - local default_node = uci:get_all(appname, default_node_id) - local main_node_id = node.main_node or "nil" - local proxy = 0 - local proxy_tag - if main_node_id ~= "nil" then - local main_node = uci:get_all(appname, main_node_id) - if main_node and api.is_normal_node(main_node) and main_node_id ~= default_node_id then - local main_node_outbound = gen_outbound(flag, main_node, "main") - if main_node_outbound then - table.insert(outbounds, main_node_outbound) - proxy = 1 - proxy_tag = "main" - local pre_proxy = nil - if default_node.type ~= "V2ray" and default_node.type ~= "Xray" then - pre_proxy = true - end - if default_node.type == "Xray" and default_node.tlsflow == "xtls-rprx-vision" then - pre_proxy = true - end - if pre_proxy then - proxy_tag = nil - new_port = get_new_port() - table.insert(inbounds, { - tag = "proxy_default", - listen = "127.0.0.1", - port = new_port, - protocol = "dokodemo-door", - settings = {network = "tcp,udp", address = default_node.address, port = tonumber(default_node.port)} - }) - if default_node.tls_serverName == nil then - default_node.tls_serverName = default_node.address - end - default_node.address = "127.0.0.1" - default_node.port = new_port - table.insert(rules, 1, { - type = "field", - inboundTag = {"proxy_default"}, - outboundTag = "main" - }) - end - end - end - end - if default_node and api.is_normal_node(default_node) then - local default_outbound = gen_outbound(flag, default_node, "default", { proxy = proxy, tag = proxy_tag, dialerProxy = node.dialerProxy }) - if default_outbound then - table.insert(outbounds, default_outbound) - default_outboundTag = "default" - end - end - end + local default_node_id = node.default_node or "_direct" + local default_outboundTag + if default_node_id == "_direct" then + default_outboundTag = "direct" + elseif default_node_id == "_blackhole" then + default_outboundTag = "blackhole" + else + local default_node = uci:get_all(appname, default_node_id) + local main_node_id = node.main_node or "nil" + local proxy = 0 + local proxy_tag + if main_node_id ~= "nil" then + local main_node = uci:get_all(appname, main_node_id) + if main_node and api.is_normal_node(main_node) and main_node_id ~= default_node_id then + local main_node_outbound = gen_outbound(flag, main_node, "main") + if main_node_outbound then + table.insert(outbounds, main_node_outbound) + proxy = 1 + proxy_tag = "main" + local pre_proxy = nil + if default_node.type ~= "V2ray" and default_node.type ~= "Xray" then + pre_proxy = true + end + if default_node.type == "Xray" and default_node.tlsflow == "xtls-rprx-vision" then + pre_proxy = true + end + if pre_proxy then + proxy_tag = nil + new_port = get_new_port() + table.insert(inbounds, { + tag = "proxy_default", + listen = "127.0.0.1", + port = new_port, + protocol = "dokodemo-door", + settings = {network = "tcp,udp", address = default_node.address, port = tonumber(default_node.port)} + }) + if default_node.tls_serverName == nil then + default_node.tls_serverName = default_node.address + end + default_node.address = "127.0.0.1" + default_node.port = new_port + table.insert(rules, 1, { + type = "field", + inboundTag = {"proxy_default"}, + outboundTag = "main" + }) + end + end + end + end + if default_node and api.is_normal_node(default_node) then + local default_outbound = gen_outbound(flag, default_node, "default", { proxy = proxy, tag = proxy_tag, dialerProxy = node.dialerProxy }) + if default_outbound then + table.insert(outbounds, default_outbound) + default_outboundTag = "default" + end + end + end - uci:foreach(appname, "shunt_rules", function(e) - local name = e[".name"] - if name and e.remarks then - local _node_id = node[name] or "nil" - local proxy_tag = node[name .. "_proxy_tag"] or "nil" - local outboundTag - if _node_id == "_direct" then - outboundTag = "direct" - elseif _node_id == "_blackhole" then - outboundTag = "blackhole" - elseif _node_id == "_default" then - outboundTag = "default" - else - if _node_id ~= "nil" then - local _node = uci:get_all(appname, _node_id) - if _node and api.is_normal_node(_node) then - local new_outbound - for index, value in ipairs(outbounds) do - if value["_flag_tag"] == _node_id and value["_flag_proxy_tag"] == proxy_tag then - new_outbound = api.clone(value) - break - end - end - if new_outbound then - new_outbound["tag"] = name - table.insert(outbounds, new_outbound) - outboundTag = name - else - local pre_proxy = nil - if _node.type ~= "V2ray" and _node.type ~= "Xray" then - pre_proxy = true - end - if _node.type == "Xray" and _node.tlsflow == "xtls-rprx-vision" then - pre_proxy = true - end - if pre_proxy then - if proxy_tag ~= "nil" then - new_port = get_new_port() - table.insert(inbounds, { - tag = "proxy_" .. name, - listen = "127.0.0.1", - port = new_port, - protocol = "dokodemo-door", - settings = {network = "tcp,udp", address = _node.address, port = tonumber(_node.port)} - }) - if _node.tls_serverName == nil then - _node.tls_serverName = _node.address - end - _node.address = "127.0.0.1" - _node.port = new_port - table.insert(rules, 1, { - type = "field", - inboundTag = {"proxy_" .. name}, - outboundTag = proxy_tag - }) - end - end - local _outbound = gen_outbound(flag, _node, name, { proxy = (proxy_tag ~= "nil") and 1 or 0, tag = (proxy_tag ~= "nil") and proxy_tag or nil, dialerProxy = node.dialerProxy }) - if _outbound then - table.insert(outbounds, _outbound) - outboundTag = name - end - end - end - end - end - if outboundTag then - if outboundTag == "default" then - outboundTag = default_outboundTag - end - local protocols = nil - if e["protocol"] and e["protocol"] ~= "" then - protocols = {} - string.gsub(e["protocol"], '[^' .. " " .. ']+', function(w) - table.insert(protocols, w) - end) - end - if e.domain_list then - local _domain = {} - string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w) - table.insert(_domain, w) - end) - table.insert(rules, { - type = "field", - outboundTag = outboundTag, - domain = _domain, - protocol = protocols - }) - end - if e.ip_list then - local _ip = {} - string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w) - table.insert(_ip, w) - end) - table.insert(rules, { - type = "field", - outboundTag = outboundTag, - ip = _ip, - protocol = protocols - }) - end - if not e.domain_list and not e.ip_list and protocols then - table.insert(rules, { - type = "field", - outboundTag = outboundTag, - protocol = protocols - }) - end - end - end - end) + uci:foreach(appname, "shunt_rules", function(e) + local name = e[".name"] + if name and e.remarks then + local _node_id = node[name] or "nil" + local proxy_tag = node[name .. "_proxy_tag"] or "nil" + local outboundTag + if _node_id == "_direct" then + outboundTag = "direct" + elseif _node_id == "_blackhole" then + outboundTag = "blackhole" + elseif _node_id == "_default" then + outboundTag = "default" + else + if _node_id ~= "nil" then + local _node = uci:get_all(appname, _node_id) + if _node and api.is_normal_node(_node) then + local new_outbound + for index, value in ipairs(outbounds) do + if value["_flag_tag"] == _node_id and value["_flag_proxy_tag"] == proxy_tag then + new_outbound = api.clone(value) + break + end + end + if new_outbound then + new_outbound["tag"] = name + table.insert(outbounds, new_outbound) + outboundTag = name + else + local pre_proxy = nil + if _node.type ~= "V2ray" and _node.type ~= "Xray" then + pre_proxy = true + end + if _node.type == "Xray" and _node.tlsflow == "xtls-rprx-vision" then + pre_proxy = true + end + if pre_proxy then + if proxy_tag ~= "nil" then + new_port = get_new_port() + table.insert(inbounds, { + tag = "proxy_" .. name, + listen = "127.0.0.1", + port = new_port, + protocol = "dokodemo-door", + settings = {network = "tcp,udp", address = _node.address, port = tonumber(_node.port)} + }) + if _node.tls_serverName == nil then + _node.tls_serverName = _node.address + end + _node.address = "127.0.0.1" + _node.port = new_port + table.insert(rules, 1, { + type = "field", + inboundTag = {"proxy_" .. name}, + outboundTag = proxy_tag + }) + end + end + local _outbound = gen_outbound(flag, _node, name, { proxy = (proxy_tag ~= "nil") and 1 or 0, tag = (proxy_tag ~= "nil") and proxy_tag or nil, dialerProxy = node.dialerProxy }) + if _outbound then + table.insert(outbounds, _outbound) + outboundTag = name + end + end + end + end + end + if outboundTag then + if outboundTag == "default" then + outboundTag = default_outboundTag + end + local protocols = nil + if e["protocol"] and e["protocol"] ~= "" then + protocols = {} + string.gsub(e["protocol"], '[^' .. " " .. ']+', function(w) + table.insert(protocols, w) + end) + end + if e.domain_list then + local _domain = {} + string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w) + table.insert(_domain, w) + end) + table.insert(rules, { + type = "field", + outboundTag = outboundTag, + domain = _domain, + protocol = protocols + }) + end + if e.ip_list then + local _ip = {} + string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w) + table.insert(_ip, w) + end) + table.insert(rules, { + type = "field", + outboundTag = outboundTag, + ip = _ip, + protocol = protocols + }) + end + if not e.domain_list and not e.ip_list and protocols then + table.insert(rules, { + type = "field", + outboundTag = outboundTag, + protocol = protocols + }) + end + end + end + end) - if default_outboundTag then - table.insert(rules, { - type = "field", - outboundTag = default_outboundTag, - network = "tcp,udp" - }) - end + if default_outboundTag then + table.insert(rules, { + type = "field", + outboundTag = default_outboundTag, + network = "tcp,udp" + }) + end - routing = { - domainStrategy = node.domainStrategy or "AsIs", - domainMatcher = node.domainMatcher or "hybrid", - rules = rules - } - elseif node.protocol == "_balancing" then - if node.balancing_node then - local nodes = node.balancing_node - local length = #nodes - for i = 1, length do - local node = uci:get_all(appname, nodes[i]) - local outbound = gen_outbound(flag, node) - if outbound then table.insert(outbounds, outbound) end - end - routing = { - domainStrategy = node.domainStrategy or "AsIs", - domainMatcher = node.domainMatcher or "hybrid", - balancers = {{tag = "balancer", selector = nodes}}, - rules = { - {type = "field", network = "tcp,udp", balancerTag = "balancer"} - } - } - end - else - local outbound = nil - if node.protocol == "_iface" then - if node.iface then - outbound = { - protocol = "freedom", - tag = "outbound", - streamSettings = { - sockopt = { - interface = node.iface - } - } - } - end - else - outbound = gen_outbound(flag, node) - end - if outbound then table.insert(outbounds, outbound) end - routing = { - domainStrategy = "AsIs", - domainMatcher = "hybrid", - rules = {} - } - end - end + routing = { + domainStrategy = node.domainStrategy or "AsIs", + domainMatcher = node.domainMatcher or "hybrid", + rules = rules + } + elseif node.protocol == "_balancing" then + if node.balancing_node then + local nodes = node.balancing_node + local length = #nodes + for i = 1, length do + local node = uci:get_all(appname, nodes[i]) + local outbound = gen_outbound(flag, node) + if outbound then table.insert(outbounds, outbound) end + end + routing = { + domainStrategy = node.domainStrategy or "AsIs", + domainMatcher = node.domainMatcher or "hybrid", + balancers = {{tag = "balancer", selector = nodes}}, + rules = { + {type = "field", network = "tcp,udp", balancerTag = "balancer"} + } + } + end + else + local outbound = nil + if node.protocol == "_iface" then + if node.iface then + outbound = { + protocol = "freedom", + tag = "outbound", + streamSettings = { + sockopt = { + interface = node.iface + } + } + } + end + else + outbound = gen_outbound(flag, node) + end + if outbound then table.insert(outbounds, outbound) end + routing = { + domainStrategy = "AsIs", + domainMatcher = "hybrid", + rules = {} + } + end + end - if remote_dns_server or remote_dns_doh_url or remote_dns_fake then - local rules = {} - local _remote_dns_proto = "tcp" - local _remote_dns_host + if remote_dns_server or remote_dns_doh_url or remote_dns_fake then + local rules = {} + local _remote_dns_proto = "tcp" + local _remote_dns_host - if not routing then - routing = { - domainStrategy = "IPOnDemand", - rules = {} - } - end + if not routing then + routing = { + domainStrategy = "IPOnDemand", + rules = {} + } + end - dns = { - tag = "dns-in1", - hosts = {}, - disableCache = (dns_cache and dns_cache == "0") and true or false, - disableFallback = true, - disableFallbackIfMatch = true, - servers = {}, - clientIp = (dns_client_ip and dns_client_ip ~= "") and dns_client_ip or nil, - queryStrategy = (dns_query_strategy and dns_query_strategy ~= "") and dns_query_strategy or "UseIPv4" - } + dns = { + tag = "dns-in1", + hosts = {}, + disableCache = (dns_cache and dns_cache == "0") and true or false, + disableFallback = true, + disableFallbackIfMatch = true, + servers = {}, + clientIp = (dns_client_ip and dns_client_ip ~= "") and dns_client_ip or nil, + queryStrategy = (dns_query_strategy and dns_query_strategy ~= "") and dns_query_strategy or "UseIPv4" + } - local _remote_dns = { - --_flag = "remote" - } + local _remote_dns = { + --_flag = "remote" + } - if remote_dns_tcp_server then - _remote_dns.address = remote_dns_tcp_server - _remote_dns.port = tonumber(remote_dns_port) - end + if remote_dns_tcp_server then + _remote_dns.address = remote_dns_tcp_server + _remote_dns.port = tonumber(remote_dns_port) + end - if remote_dns_doh_url and remote_dns_doh_host then - if remote_dns_server and remote_dns_doh_host ~= remote_dns_server and not api.is_ip(remote_dns_doh_host) then - dns.hosts[remote_dns_doh_host] = remote_dns_server - _remote_dns_host = remote_dns_doh_host - end - _remote_dns.address = remote_dns_doh_url - _remote_dns.port = tonumber(remote_dns_port) - _remote_dns_proto = "doh" - end + if remote_dns_doh_url and remote_dns_doh_host then + if remote_dns_server and remote_dns_doh_host ~= remote_dns_server and not api.is_ip(remote_dns_doh_host) then + dns.hosts[remote_dns_doh_host] = remote_dns_server + _remote_dns_host = remote_dns_doh_host + end + _remote_dns.address = remote_dns_doh_url + _remote_dns.port = tonumber(remote_dns_port) + _remote_dns_proto = "doh" + end - if remote_dns_fake then - remote_dns_server = "1.1.1.1" - fakedns = {} - fakedns[#fakedns + 1] = { - ipPool = "198.18.0.0/16", - poolSize = 65535 - } - if dns_query_strategy == "UseIP" then - fakedns[#fakedns + 1] = { - ipPool = "fc00::/18", - poolSize = 65535 - } - end - _remote_dns.address = "fakedns" - end + if remote_dns_fake then + remote_dns_server = "1.1.1.1" + fakedns = {} + fakedns[#fakedns + 1] = { + ipPool = "198.18.0.0/16", + poolSize = 65535 + } + if dns_query_strategy == "UseIP" then + fakedns[#fakedns + 1] = { + ipPool = "fc00::/18", + poolSize = 65535 + } + end + _remote_dns.address = "fakedns" + end - table.insert(dns.servers, _remote_dns) + table.insert(dns.servers, _remote_dns) - if dns_listen_port then - table.insert(inbounds, { - listen = "127.0.0.1", - port = tonumber(dns_listen_port), - protocol = "dokodemo-door", - tag = "dns-in", - settings = { - address = remote_dns_server, - port = (_remote_dns_proto ~= "doh" and tonumber(remote_dns_port)) and tonumber(remote_dns_port) or 53, - network = "tcp,udp" - } - }) + if dns_listen_port then + table.insert(inbounds, { + listen = "127.0.0.1", + port = tonumber(dns_listen_port), + protocol = "dokodemo-door", + tag = "dns-in", + settings = { + address = remote_dns_server, + port = (_remote_dns_proto ~= "doh" and tonumber(remote_dns_port)) and tonumber(remote_dns_port) or 53, + network = "tcp,udp" + } + }) - table.insert(outbounds, { - tag = "dns-out", - protocol = "dns", - settings = { - address = remote_dns_server, - port = (_remote_dns_proto ~= "doh" and tonumber(remote_dns_port)) and tonumber(remote_dns_port) or 53, - network = "tcp", - } - }) + table.insert(outbounds, { + tag = "dns-out", + protocol = "dns", + settings = { + address = remote_dns_server, + port = (_remote_dns_proto ~= "doh" and tonumber(remote_dns_port)) and tonumber(remote_dns_port) or 53, + network = "tcp", + } + }) - table.insert(routing.rules, 1, { - type = "field", - inboundTag = { - "dns-in" - }, - outboundTag = "dns-out" - }) - end + table.insert(routing.rules, 1, { + type = "field", + inboundTag = { + "dns-in" + }, + outboundTag = "dns-out" + }) + end - --[[ - local default_dns_flag = "remote" - if node_id and tcp_redir_port then - local node = uci:get_all(appname, node_id) - if node.protocol == "_shunt" then - if node.default_node == "_direct" then - default_dns_flag = "direct" - end - end - end + --[[ + local default_dns_flag = "remote" + if node_id and tcp_redir_port then + local node = uci:get_all(appname, node_id) + if node.protocol == "_shunt" then + if node.default_node == "_direct" then + default_dns_flag = "direct" + end + end + end - if dns.servers and #dns.servers > 0 then - local dns_servers = nil - for index, value in ipairs(dns.servers) do - if not dns_servers and value["_flag"] == default_dns_flag then - dns_servers = { - _flag = "default", - address = value.address, - port = value.port - } - break - end - end - if dns_servers then - table.insert(dns.servers, 1, dns_servers) - end - end - ]]-- - if true then - local dns_outboundTag = "direct" - if dns_socks_address and dns_socks_port then - dns_outboundTag = "out" - table.insert(outbounds, 1, { - tag = dns_outboundTag, - protocol = "socks", - streamSettings = { - network = "tcp", - security = "none", - sockopt = { - mark = 255 - } - }, - settings = { - servers = { - { - address = dns_socks_address, - port = tonumber(dns_socks_port) - } - } - } - }) - else - if node_id and tcp_redir_port and not remote_dns_fake then - dns_outboundTag = node_id - local node = uci:get_all(appname, node_id) - if node.protocol == "_shunt" then - dns_outboundTag = "default" - end - end - end - table.insert(rules, { - type = "field", - inboundTag = { - "dns-in1" - }, - ip = { - remote_dns_server - }, - port = tonumber(remote_dns_port), - outboundTag = dns_outboundTag - }) - if _remote_dns_host then - table.insert(rules, { - type = "field", - inboundTag = { - "dns-in1" - }, - domain = { - _remote_dns_host - }, - port = tonumber(remote_dns_port), - outboundTag = dns_outboundTag - }) - end - end + if dns.servers and #dns.servers > 0 then + local dns_servers = nil + for index, value in ipairs(dns.servers) do + if not dns_servers and value["_flag"] == default_dns_flag then + dns_servers = { + _flag = "default", + address = value.address, + port = value.port + } + break + end + end + if dns_servers then + table.insert(dns.servers, 1, dns_servers) + end + end + ]]-- + if true then + local dns_outboundTag = "direct" + if dns_socks_address and dns_socks_port then + dns_outboundTag = "out" + table.insert(outbounds, 1, { + tag = dns_outboundTag, + protocol = "socks", + streamSettings = { + network = "tcp", + security = "none", + sockopt = { + mark = 255 + } + }, + settings = { + servers = { + { + address = dns_socks_address, + port = tonumber(dns_socks_port) + } + } + } + }) + else + if node_id and tcp_redir_port and not remote_dns_fake then + dns_outboundTag = node_id + local node = uci:get_all(appname, node_id) + if node.protocol == "_shunt" then + dns_outboundTag = "default" + end + end + end + table.insert(rules, { + type = "field", + inboundTag = { + "dns-in1" + }, + ip = { + remote_dns_server + }, + port = tonumber(remote_dns_port), + outboundTag = dns_outboundTag + }) + if _remote_dns_host then + table.insert(rules, { + type = "field", + inboundTag = { + "dns-in1" + }, + domain = { + _remote_dns_host + }, + port = tonumber(remote_dns_port), + outboundTag = dns_outboundTag + }) + end + end - local default_rule_index = #routing.rules > 0 and #routing.rules or 1 - for index, value in ipairs(routing.rules) do - if value["_flag"] == "default" then - default_rule_index = index - break - end - end - for index, value in ipairs(rules) do - local t = rules[#rules + 1 - index] - table.insert(routing.rules, default_rule_index, t) - end + local default_rule_index = #routing.rules > 0 and #routing.rules or 1 + for index, value in ipairs(routing.rules) do + if value["_flag"] == "default" then + default_rule_index = index + break + end + end + for index, value in ipairs(rules) do + local t = rules[#rules + 1 - index] + table.insert(routing.rules, default_rule_index, t) + end - local dns_hosts_len = 0 - for key, value in pairs(dns.hosts) do - dns_hosts_len = dns_hosts_len + 1 - end + local dns_hosts_len = 0 + for key, value in pairs(dns.hosts) do + dns_hosts_len = dns_hosts_len + 1 + end - if dns_hosts_len == 0 then - dns.hosts = nil - end - end + if dns_hosts_len == 0 then + dns.hosts = nil + end + end - if inbounds or outbounds then - local config = { - log = { - -- error = string.format("/tmp/etc/%s/%s.log", appname, node[".name"]), - loglevel = loglevel - }, - -- DNS - dns = dns, - fakedns = fakedns, - -- 传入连接 - inbounds = inbounds, - -- 传出连接 - outbounds = outbounds, - -- 路由 - routing = routing, - -- 本地策略 - policy = { - levels = { - [0] = { - -- handshake = 4, - -- connIdle = 300, - -- uplinkOnly = 2, - -- downlinkOnly = 5, - bufferSize = buffer_size and tonumber(buffer_size) or nil, - statsUserUplink = false, - statsUserDownlink = false - } - }, - -- system = { - -- statsInboundUplink = false, - -- statsInboundDownlink = false - -- } - } - } - table.insert(outbounds, { - protocol = "freedom", - tag = "direct", - settings = { - domainStrategy = (dns_query_strategy and dns_query_strategy ~= "") and dns_query_strategy or "UseIPv4" - }, - streamSettings = { - sockopt = { - mark = 255 - } - } - }) - table.insert(outbounds, { - protocol = "blackhole", - tag = "blackhole" - }) - return jsonc.stringify(config, 1) - end + if inbounds or outbounds then + local config = { + log = { + -- error = string.format("/tmp/etc/%s/%s.log", appname, node[".name"]), + loglevel = loglevel + }, + -- DNS + dns = dns, + fakedns = fakedns, + -- 传入连接 + inbounds = inbounds, + -- 传出连接 + outbounds = outbounds, + -- 路由 + routing = routing, + -- 本地策略 + policy = { + levels = { + [0] = { + -- handshake = 4, + -- connIdle = 300, + -- uplinkOnly = 2, + -- downlinkOnly = 5, + bufferSize = buffer_size and tonumber(buffer_size) or nil, + statsUserUplink = false, + statsUserDownlink = false + } + }, + -- system = { + -- statsInboundUplink = false, + -- statsInboundDownlink = false + -- } + } + } + table.insert(outbounds, { + protocol = "freedom", + tag = "direct", + settings = { + domainStrategy = (dns_query_strategy and dns_query_strategy ~= "") and dns_query_strategy or "UseIPv4" + }, + streamSettings = { + sockopt = { + mark = 255 + } + } + }) + table.insert(outbounds, { + protocol = "blackhole", + tag = "blackhole" + }) + return jsonc.stringify(config, 1) + end end function gen_proto_config(var) - local local_socks_address = var["-local_socks_address"] or "0.0.0.0" - local local_socks_port = var["-local_socks_port"] - local local_socks_username = var["-local_socks_username"] - local local_socks_password = var["-local_socks_password"] - local local_http_address = var["-local_http_address"] or "0.0.0.0" - local local_http_port = var["-local_http_port"] - local local_http_username = var["-local_http_username"] - local local_http_password = var["-local_http_password"] - local server_proto = var["-server_proto"] - local server_address = var["-server_address"] - local server_port = var["-server_port"] - local server_username = var["-server_username"] - local server_password = var["-server_password"] + local local_socks_address = var["-local_socks_address"] or "0.0.0.0" + local local_socks_port = var["-local_socks_port"] + local local_socks_username = var["-local_socks_username"] + local local_socks_password = var["-local_socks_password"] + local local_http_address = var["-local_http_address"] or "0.0.0.0" + local local_http_port = var["-local_http_port"] + local local_http_username = var["-local_http_username"] + local local_http_password = var["-local_http_password"] + local server_proto = var["-server_proto"] + local server_address = var["-server_address"] + local server_port = var["-server_port"] + local server_username = var["-server_username"] + local server_password = var["-server_password"] - local inbounds = {} - local outbounds = {} - local routing = nil + local inbounds = {} + local outbounds = {} + local routing = nil - if local_socks_address and local_socks_port then - local inbound = { - listen = local_socks_address, - port = tonumber(local_socks_port), - protocol = "socks", - settings = { - udp = true, - auth = "noauth" - } - } - if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then - inbound.settings.auth = "password" - inbound.settings.accounts = { - { - user = local_socks_username, - pass = local_socks_password - } - } - end - table.insert(inbounds, inbound) - end + if local_socks_address and local_socks_port then + local inbound = { + listen = local_socks_address, + port = tonumber(local_socks_port), + protocol = "socks", + settings = { + udp = true, + auth = "noauth" + } + } + if local_socks_username and local_socks_password and local_socks_username ~= "" and local_socks_password ~= "" then + inbound.settings.auth = "password" + inbound.settings.accounts = { + { + user = local_socks_username, + pass = local_socks_password + } + } + end + table.insert(inbounds, inbound) + end - if local_http_address and local_http_port then - local inbound = { - listen = local_http_address, - port = tonumber(local_http_port), - protocol = "http", - settings = { - allowTransparent = false - } - } - if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then - inbound.settings.accounts = { - { - user = local_http_username, - pass = local_http_password - } - } - end - table.insert(inbounds, inbound) - end + if local_http_address and local_http_port then + local inbound = { + listen = local_http_address, + port = tonumber(local_http_port), + protocol = "http", + settings = { + allowTransparent = false + } + } + if local_http_username and local_http_password and local_http_username ~= "" and local_http_password ~= "" then + inbound.settings.accounts = { + { + user = local_http_username, + pass = local_http_password + } + } + end + table.insert(inbounds, inbound) + end - if server_proto ~= "nil" and server_address ~= "nil" and server_port ~= "nil" then - local outbound = { - protocol = server_proto, - streamSettings = { - network = "tcp", - security = "none" - }, - settings = { - servers = { - { - address = server_address, - port = tonumber(server_port), - users = (server_username and server_password) and { - { - user = server_username, - pass = server_password - } - } or nil - } - } - } - } - if outbound then table.insert(outbounds, outbound) end - end + if server_proto ~= "nil" and server_address ~= "nil" and server_port ~= "nil" then + local outbound = { + protocol = server_proto, + streamSettings = { + network = "tcp", + security = "none" + }, + settings = { + servers = { + { + address = server_address, + port = tonumber(server_port), + users = (server_username and server_password) and { + { + user = server_username, + pass = server_password + } + } or nil + } + } + } + } + if outbound then table.insert(outbounds, outbound) end + end - -- 额外传出连接 - table.insert(outbounds, { - protocol = "freedom", tag = "direct", settings = {keep = ""}, sockopt = {mark = 255} - }) + -- 额外传出连接 + table.insert(outbounds, { + protocol = "freedom", tag = "direct", settings = {keep = ""}, sockopt = {mark = 255} + }) - local config = { - log = { - loglevel = "warning" - }, - -- 传入连接 - inbounds = inbounds, - -- 传出连接 - outbounds = outbounds, - -- 路由 - routing = routing - } - return jsonc.stringify(config, 1) + local config = { + log = { + loglevel = "warning" + }, + -- 传入连接 + inbounds = inbounds, + -- 传出连接 + outbounds = outbounds, + -- 路由 + routing = routing + } + return jsonc.stringify(config, 1) end _G.gen_config = gen_config _G.gen_proto_config = gen_proto_config if arg[1] then - local func =_G[arg[1]] - if func then - print(func(api.get_function_args(arg))) - end + local func =_G[arg[1]] + if func then + print(func(api.get_function_args(arg))) + end end diff --git a/luci-app-passwall/luasrc/view/passwall/app_update/app_version.htm b/luci-app-passwall/luasrc/view/passwall/app_update/app_version.htm index 824c67291..3984908f0 100644 --- a/luci-app-passwall/luasrc/view/passwall/app_update/app_version.htm +++ b/luci-app-passwall/luasrc/view/passwall/app_update/app_version.htm @@ -37,7 +37,6 @@ local version = {} if (inProgressCount === 0) { window.onbeforeunload = undefined; } - } function onUpdateSuccess(btn) { @@ -190,4 +189,4 @@ local version = {} -<%end%> \ No newline at end of file +<%end%> diff --git a/luci-app-passwall/luasrc/view/passwall/auto_switch/footer.htm b/luci-app-passwall/luasrc/view/passwall/auto_switch/footer.htm index bb6f2cc02..6d65aaa8f 100644 --- a/luci-app-passwall/luasrc/view/passwall/auto_switch/footer.htm +++ b/luci-app-passwall/luasrc/view/passwall/auto_switch/footer.htm @@ -10,6 +10,7 @@ local api = require "luci.passwall.api" window.location.href = '<%=api.url("autoswitch_add_node")%>' + "?key=" + key; } } + function remove_node_by_key() { var key = prompt("<%:Please enter the node keyword, pay attention to distinguish between spaces, uppercase and lowercase.%>", ""); if (key) { @@ -19,4 +20,4 @@ local api = require "luci.passwall.api" //]]> - \ No newline at end of file + diff --git a/luci-app-passwall/luasrc/view/passwall/global/faq.htm b/luci-app-passwall/luasrc/view/passwall/global/faq.htm index d55f7792d..10c58c5e6 100644 --- a/luci-app-passwall/luasrc/view/passwall/global/faq.htm +++ b/luci-app-passwall/luasrc/view/passwall/global/faq.htm @@ -18,19 +18,19 @@ local api = require "luci.passwall.api" var reset_url = origin + "<%=api.url("reset_config")%>"; var hide_url = origin + "<%=api.url("hide")%>"; var show_url = origin + "<%=api.url("show")%>"; - + function reset(url) { if (confirm('<%:Are you sure to reset?%>') == true) { window.location.href = reset_url; } } - + function hide(url) { if (confirm('<%:Are you sure to hide?%>') == true) { window.location.href = hide_url; } } - + var dom = document.getElementById("div2"); if (dom) { var li = ""; diff --git a/luci-app-passwall/luasrc/view/passwall/global/footer.htm b/luci-app-passwall/luasrc/view/passwall/global/footer.htm index 7ceff86f1..8b63d563e 100644 --- a/luci-app-passwall/luasrc/view/passwall/global/footer.htm +++ b/luci-app-passwall/luasrc/view/passwall/global/footer.htm @@ -17,7 +17,7 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0) var div = ''; var div1 = ' '; var div2 = 'X '; - + if (result.socks_status) { div += div1; } else { @@ -34,7 +34,7 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0) } ); } - + var global_id = null; var global = document.getElementById("cbi-passwall-global"); if (global) { @@ -69,15 +69,15 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0) } else { node_select.title = node_select.options[node_select.options.selectedIndex].text; } - + var new_html = ""; - + var new_a = document.createElement("a"); new_a.innerHTML = "<%:Edit%>"; new_a.href = "#"; new_a.setAttribute("onclick", "location.href='" + '<%=api.url("node_config")%>' + "/" + node_select_value + "'"); new_html = new_a.outerHTML; - + if (s[0] == "tcp" || s[0] == "udp") { var log_a = document.createElement("a"); log_a.innerHTML = "<%:Log%>"; @@ -85,7 +85,7 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0) log_a.setAttribute("onclick", "window.open('" + '<%=api.url("get_redir_log")%>' + "?proto=" + s[0] + "', '_blank')"); new_html += "  " + log_a.outerHTML; } - + node_select.insertAdjacentHTML("afterend", "  " + new_html); } } @@ -96,7 +96,7 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0) } } } - + var socks = document.getElementById("cbi-passwall-socks"); if (socks) { var socks_enabled_dom = document.getElementById(global_id + "-socks_enabled"); @@ -121,12 +121,12 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0) } else { node_select.title = node_select.options[node_select.options.selectedIndex].text; } - + var new_a = document.createElement("a"); new_a.innerHTML = "<%:Edit%>"; new_a.href = "#"; new_a.setAttribute("onclick","location.href='" + '<%=api.url("node_config")%>' + "/" + node_select_value + "'"); - + node_select.insertAdjacentHTML("afterend", "  " + new_a.outerHTML); } } catch(err) { @@ -137,4 +137,4 @@ local auto_switch = api.uci_get_type("auto_switch", "enable", 0) setTimeout("go()", 1000); //]]> - \ No newline at end of file + diff --git a/luci-app-passwall/luasrc/view/passwall/global/status.htm b/luci-app-passwall/luasrc/view/passwall/global/status.htm index d75375dc4..4f6945694 100644 --- a/luci-app-passwall/luasrc/view/passwall/global/status.htm +++ b/luci-app-passwall/luasrc/view/passwall/global/status.htm @@ -100,7 +100,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md margin: 1rem 0rem 1rem 0.5rem; } } - + @media screen and (max-width: 480px) { .img-con { margin: 1.5rem 0.5rem; @@ -237,7 +237,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md status_tcp_node.innerHTML = text; } } - + if (true) { var status_udp_node = document.getElementById('status_udp_node'); if (status_udp_node) { @@ -249,7 +249,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md status_udp_node.innerHTML = text; } } - + if (data.dns_mode_status) { status_dns.innerHTML = 'DNS
      <%:RUNNING%>'; } else { @@ -264,7 +264,7 @@ https://github.com/pure-css/pure/blob/master/LICENSE.md } } }); - + function check_connect(type, url) { var s = document.getElementById('_' + type + '_status'); if (s) { diff --git a/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm b/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm index 578f43383..6d584583f 100644 --- a/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm +++ b/luci-app-passwall/luasrc/view/passwall/haproxy/status.htm @@ -18,7 +18,7 @@ local console_port = api.uci_get_type("global_haproxy", "console_port", "") } } }); - + function openwebui(){ var url = window.location.hostname + ":<%=console_port%>"; window.open('http://' + url, 'target', ''); diff --git a/luci-app-passwall/luasrc/view/passwall/log/log.htm b/luci-app-passwall/luasrc/view/passwall/log/log.htm index a9dee2948..42be485c5 100644 --- a/luci-app-passwall/luasrc/view/passwall/log/log.htm +++ b/luci-app-passwall/luasrc/view/passwall/log/log.htm @@ -14,6 +14,7 @@ local api = require "luci.passwall.api" } ); } + XHR.poll(5, '<%=api.url("get_log")%>', null, function(x, data) { if(x && x.status == 200) { diff --git a/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm b/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm index e6922121e..cbc43216c 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_list/link_add_node.htm @@ -13,7 +13,7 @@ local api = require "luci.passwall.api" z-index: 99; text-align: center; background: white; - box-shadow: darkgrey 10px 10px 30px 5px; + box-shadow: darkgrey 10px 10px 30px 5px; padding: 30px 15px; } @@ -35,16 +35,16 @@ local api = require "luci.passwall.api" }); } } - + function open_add_link_div() { document.getElementById("add_link_div").style.display = "block"; document.getElementById("nodes_link").focus(); } - + function close_add_link_div() { document.getElementById("add_link_div").style.display = "none"; } - + function add_node() { var nodes_link = document.getElementById("nodes_link").value; if (nodes_link.trim() != "") { @@ -61,7 +61,7 @@ local api = require "luci.passwall.api" document.getElementById("nodes_link").focus(); } } - + function clear_all_nodes() { if (confirm('<%:Are you sure to clear all nodes?%>') == true){ XHR.get('<%=api.url("clear_all_nodes")%>', null, @@ -75,7 +75,7 @@ local api = require "luci.passwall.api" }); } } - + //]]> @@ -105,4 +105,4 @@ local api = require "luci.passwall.api"
      - \ No newline at end of file + 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 30e926ebf..b850976cc 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 @@ -8,23 +8,23 @@ local has_xray = api.is_finded("xray") function padright(str, cnt, pad) { return str + Array(cnt + 1).join(pad); } - + function b64EncodeUnicode(str) { return btoa(encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function(match, p1) { return String.fromCharCode('0x' + p1); })); } - + function b64encutf8safe(str) { return b64EncodeUnicode(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, ''); } - + function b64DecodeUnicode(str) { return decodeURIComponent(Array.prototype.map.call(atob(str), function(c) { return '%' + ('00' + c.charCodeAt(0).toString(16)).slice(-2); }).join('')); } - + function b64decutf8safe(str) { var l; str = str.replace(/-/g, "+").replace(/_/g, "/"); @@ -34,11 +34,11 @@ local has_xray = api.is_finded("xray") str = padright(str, l, "="); return b64DecodeUnicode(str); } - + function b64encsafe(str) { return btoa(str).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, '') } - + function b64decsafe(str) { var l; str = str.replace(/-/g, "+").replace(/_/g, "/"); @@ -48,13 +48,14 @@ local has_xray = api.is_finded("xray") str = padright(str, l, "="); return atob(str); } - + function dictvalue(d, key) { var v = d[key]; if (typeof(v) === 'undefined' || v === '') return ''; return b64decsafe(v); } + function parseNodeUrl(url) { var m = url.match(/^(([^:\/?#]+:)?(?:\/\/((?:([^\/?#:]*)([^\/?#:]*)@)?([^\/?#:]*)(?::([^\/?#:]*))?)))?([^?#]*)(\?[^#]*)?(#.*)?$/), r = { @@ -120,7 +121,7 @@ local has_xray = api.is_finded("xray") return "" } } - + var s = document.getElementById(urlname + "-status"); if (!s) { alert("Never"); @@ -136,11 +137,11 @@ local has_xray = api.is_finded("xray") var v_port = opt.get("port"); var v_method = opt.get("ss_encrypt_method"); var v_password = opt.get("password"); - + url = b64encsafe(v_method.value + ":" + v_password.value) + "@" + v_server.value + ":" + v_port.value + "/?"; - + var params = ""; var v_plugin = opt.get("ss_plugin").value; if (v_plugin && v_plugin != "none") { @@ -165,11 +166,11 @@ local has_xray = api.is_finded("xray") var v_port = opt.get("port"); var v_method = opt.get("ss_rust_encrypt_method"); var v_password = opt.get("password"); - + url = btoa(v_method.value + ":" + v_password.value) + "@" + v_server.value + ":" + v_port.value + "/?"; - + var params = ""; var v_plugin = opt.get("ss_plugin").value; if (v_plugin && v_plugin != "none") { @@ -215,7 +216,7 @@ local has_xray = api.is_finded("xray") info.add = opt.get("address").value; info.port = opt.get("port").value; info.id = opt.get("uuid").value; - + var v_transport = opt.get("transport").value; if (v_transport === "ws") { info.host = opt.get("ws_host").value; @@ -241,7 +242,7 @@ local has_xray = api.is_finded("xray") info.path = encodeURI(info.path); } info.net = v_transport; - + info.security = opt.get("security").value || "auto"; if (opt.get("tls").checked) { var v_security = "tls"; @@ -257,7 +258,7 @@ local has_xray = api.is_finded("xray") url = encodeURIComponent(v_password.value) + "@" + v_server.value + ":" + v_port.value + "?"; - + var params = ""; var v_transport = opt.get("transport").value; if (v_transport === "ws") { @@ -283,7 +284,7 @@ local has_xray = api.is_finded("xray") params += opt.query("serviceName", "grpc_serviceName"); } params += "&type=" + v_transport; - + params += opt.query("encryption", "encryption"); if (opt.get("tls").checked) { @@ -365,7 +366,7 @@ local has_xray = api.is_finded("xray") var v_port = opt.get("port"); var v_password = opt.get("password"); var b_protocol_value = v_protocol.value.split('client').join('server'); - + var url_protocol = b_protocol_value; params += opt.query("password", "password"); if (b_protocol_value == "wsserver") { @@ -425,7 +426,7 @@ local has_xray = api.is_finded("xray") } return false; } - + function fromUrl(btn, urlname, sid) { var opt = { base: 'cbid.passwall', @@ -461,7 +462,7 @@ local has_xray = api.is_finded("xray") if (obj.combobox) { obj.combobox.value = val; } - + var list = obj.getElementsByTagName("li"); if (list.length > 0) { for (var i = 0; i < list.length; i++) { @@ -508,7 +509,7 @@ local has_xray = api.is_finded("xray") } } } - + var s = document.getElementById(urlname + '-status'); if (!s) { alert("Never"); @@ -659,7 +660,7 @@ local has_xray = api.is_finded("xray") opt.set('tls_serverName', queryParam.peer || queryParam.sni || ''); opt.set('tls_allowInsecure', queryParam.allowinsecure === '1'); } - + if (stype === "Trojan-Go") { var tran = 'original'; var ws = null; @@ -849,7 +850,7 @@ local has_xray = api.is_finded("xray") queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || ''); } } - + opt.set('encryption', queryParam.encryption); if (queryParam.security) { if (queryParam.security == "tls") { @@ -865,7 +866,7 @@ local has_xray = api.is_finded("xray") } } } - + queryParam.type = queryParam.type.toLowerCase(); if (queryParam.type === "kcp" || queryParam.type === "mkcp") queryParam.type = "mkcp" @@ -891,17 +892,17 @@ local has_xray = api.is_finded("xray") } else if (queryParam.type === "grpc") { opt.set('grpc_serviceName', (queryParam.serviceName || queryParam.path) || ""); } - + if (m.hash) { opt.set('remarks', decodeURI(m.hash.substr(1))); } } else if (ssu[0] === "brook") { var stype = "Brook"; var m = parseNodeUrl(ssrurl); - + var from_protocol = m.host; var protocol = from_protocol.split('server').join('client'); - + var queryParam = {}; if (m.search.length > 1) { var query = m.search.split('?'); @@ -913,17 +914,17 @@ local has_xray = api.is_finded("xray") queryParam[decodeURIComponent(params[0])] = decodeURIComponent(params[1] || ''); } } - + var password = queryParam.password; if (password === "") { s.innerHTML = "<%:Invalid Share URL Format%>"; return false; } - + opt.set('type', stype); opt.set('brook_protocol', protocol); opt.set('password', password); - + if (protocol == 'wsclient' || protocol == 'wssclient') { opt.set('brook_protocol', 'wsclient'); var wsserver = queryParam[from_protocol].split('://'); @@ -945,7 +946,7 @@ local has_xray = api.is_finded("xray") opt.set('address', server[0]); opt.set('port', server[1]); } - + if (m.hash) { opt.set('remarks', decodeURI(m.hash.substr(1))); } diff --git a/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm b/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm index a0dceb615..4125f38ab 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_list/node_list.htm @@ -9,8 +9,8 @@ table th, .table .th { table td, .table .td { text-align: center; - /* white-space: nowrap; */ - word-break: keep-all; + /* white-space: nowrap; */ + word-break: keep-all; } #set_node_div { @@ -22,7 +22,7 @@ table td, .table .td { z-index: 99; text-align: center; background: white; - box-shadow: darkgrey 10px 10px 30px 5px; + box-shadow: darkgrey 10px 10px 30px 5px; } ._now_use { @@ -38,14 +38,14 @@ table td, .table .td { // 1000) { xhr.timeout = timeout; } @@ -89,11 +89,11 @@ table td, .table .td { return obj; } } - + function copy_node(cbi_id) { window.location.href = '<%=api.url("copy_node")%>' + "?section=" + cbi_id; } - + var section = ""; function open_set_node_div(cbi_id) { section = cbi_id; @@ -101,12 +101,12 @@ table td, .table .td { var node_name = document.getElementById("cbid.passwall." + cbi_id + ".remarks").value; document.getElementById("set_node_name").innerHTML = node_name; } - + function close_set_node_div() { document.getElementById("set_node_div").style.display="none"; document.getElementById("set_node_name").innerHTML = ""; } - + function _cbi_row_top(id) { var dom = document.getElementById("cbi-passwall-" + id); if (dom) { @@ -121,7 +121,7 @@ table td, .table .td { } } } - + function checked_all_node(btn) { var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select"); if (doms && doms.length > 0) { @@ -132,7 +132,7 @@ table td, .table .td { btn.setAttribute("onclick", "dechecked_all_node(this)"); } } - + function dechecked_all_node(btn) { var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select"); if (doms && doms.length > 0) { @@ -143,7 +143,7 @@ table td, .table .td { btn.setAttribute("onclick", "checked_all_node(this)"); } } - + function delete_select_nodes() { var ids = []; var doms = document.getElementById("cbi-passwall-nodes").getElementsByClassName("nodes_select"); @@ -179,13 +179,13 @@ table td, .table .td { alert("<%:You no select nodes !%>"); } } - + function set_node(protocol) { if (confirm('<%:Are you sure set to%> ' + protocol.toUpperCase() + '<%:the server?%>')==true){ window.location.href = '<%=api.url("set_node")%>?protocol=' + protocol + '§ion=' + section; } } - + function get_address_full(id) { try { var address = document.getElementById("cbid.passwall." + id + ".address").value; @@ -200,7 +200,7 @@ table td, .table .td { return null; } } - + //获取当前使用的节点 function get_now_use_node() { XHR.get('<%=api.url("get_now_use_node")%>', null, @@ -226,7 +226,7 @@ table td, .table .td { } ); } - + function urltest_node(cbi_id, dom) { if (cbi_id != null) { dom.disabled = true; @@ -255,7 +255,7 @@ table td, .table .td { ); } } - + function ping_node(cbi_id, dom) { var full = get_address_full(cbi_id); if (full != null) { @@ -281,7 +281,7 @@ table td, .table .td { ); } } - + /* 自动Ping */ var nodes = []; const ping_value = document.getElementsByClassName('ping_value'); @@ -307,9 +307,9 @@ table td, .table .td { }); } } - + get_now_use_node(); - + const _xhr = (index) => { return new Promise((res) => { const dom = nodes[index]; @@ -349,7 +349,7 @@ table td, .table .td { ); }) } - + let task = -1; const thread = () => { task = task + 1 @@ -360,7 +360,7 @@ table td, .table .td { for (let i = 0; i < 20; i++) { thread() } - + /* 递归单请求方法 var index = 0; function auto_ping() { @@ -407,7 +407,7 @@ table td, .table .td { } auto_ping(); */ - + var edit_btn = document.getElementById("cbi-passwall-nodes").getElementsByClassName("cbi-button cbi-button-edit"); for (var i = 0; i < edit_btn.length; i++) { try { @@ -424,7 +424,7 @@ table td, .table .td { //添加"复制"按钮 new_div += '  '; td.innerHTML = new_div + td.innerHTML; - + var obj = {}; obj.id = id; obj.type = document.getElementById("cbid.passwall." + id + ".type").value; @@ -434,20 +434,20 @@ table td, .table .td { obj.address = address_dom.value; obj.port = port_dom.value; } - + node_count++; var add_from = document.getElementById("cbid.passwall." + id + ".add_from").value; if (node_list[add_from]) node_list[add_from].push(obj); else node_list[add_from] = []; - + } catch(err) { console.error(err); } } - + if (true) { var str = ""; for (var add_from in node_list) { @@ -459,7 +459,7 @@ table td, .table .td { } document.getElementById("div_node_count").innerHTML = "
      " + str + "
      "; } - + //]]> @@ -472,4 +472,4 @@ table td, .table .td { - \ No newline at end of file + diff --git a/luci-app-passwall/luasrc/view/passwall/server/log.htm b/luci-app-passwall/luasrc/view/passwall/server/log.htm index b9c1253de..024ee335c 100644 --- a/luci-app-passwall/luasrc/view/passwall/server/log.htm +++ b/luci-app-passwall/luasrc/view/passwall/server/log.htm @@ -14,6 +14,7 @@ local api = require "luci.passwall.api" } ); } + XHR.poll(3, '<%=api.url("server_get_log")%>', null, function(x, data) { if(x && x.status == 200) { @@ -31,4 +32,4 @@ local api = require "luci.passwall.api" - \ No newline at end of file + diff --git a/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm b/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm index d2c18630a..8ba385aaf 100644 --- a/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm +++ b/luci-app-passwall/luasrc/view/passwall/server/users_list_status.htm @@ -18,7 +18,7 @@ local api = require "luci.passwall.api" } ); } - + var edit_btn = document.getElementById("cbi-passwall_server-user").getElementsByClassName("cbi-button cbi-button-edit"); for (var i = 0; i < edit_btn.length; i++) { try { @@ -35,4 +35,4 @@ local api = require "luci.passwall.api" } } //]]> - \ No newline at end of file + diff --git a/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua b/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua index e973b5799..c9b3f9cb2 100644 --- a/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua +++ b/luci-app-passwall/root/usr/share/passwall/helper_dnsmasq_add.lua @@ -33,133 +33,133 @@ local excluded_domain = {} local excluded_domain_str = "!" local function log(...) - if NO_LOGIC_LOG == "1" then - return - end + if NO_LOGIC_LOG == "1" then + return + end local f, err = io.open(LOG_FILE, "a") - if f and err == nil then - local str = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") - f:write(str .. "\n") - f:close() - end + if f and err == nil then + local str = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") + f:write(str .. "\n") + f:close() + end end local function check_dns(domain, dns) - if domain == "" or domain:find("#") then - return false - end - if not dns then - return - end + if domain == "" or domain:find("#") then + return false + end + if not dns then + return + end for k,v in ipairs(list1[domain].dns) do if dns == v then return true end end - return false + return false end local function check_ipset(domain, ipset) - if domain == "" or domain:find("#") then - return false - end - if not ipset then - return - end + if domain == "" or domain:find("#") then + return false + end + if not ipset then + return + end for k,v in ipairs(list1[domain].ipsets) do if ipset == v then return true end end - return false + return false end local function set_domain_address(domain, address) - if domain == "" or domain:find("#") then - return - end - if not list1[domain] then - list1[domain] = { - dns = {}, - ipsets = {} - } - end - if not list1[domain].address then - list1[domain].address = address - end + if domain == "" or domain:find("#") then + return + end + if not list1[domain] then + list1[domain] = { + dns = {}, + ipsets = {} + } + end + if not list1[domain].address then + list1[domain].address = address + end end local function set_domain_dns(domain, dns) - if domain == "" or domain:find("#") then - return - end - if not dns then - return - end - if not list1[domain] then - list1[domain] = { - dns = {}, - ipsets = {} - } - end - for line in string.gmatch(dns, '[^' .. "," .. ']+') do - if not check_dns(domain, line) then - table.insert(list1[domain].dns, line) - end - end + if domain == "" or domain:find("#") then + return + end + if not dns then + return + end + if not list1[domain] then + list1[domain] = { + dns = {}, + ipsets = {} + } + end + for line in string.gmatch(dns, '[^' .. "," .. ']+') do + if not check_dns(domain, line) then + table.insert(list1[domain].dns, line) + end + end end local function set_domain_ipset(domain, ipset) - if domain == "" or domain:find("#") then - return - end - if not ipset then - return - end - if not list1[domain] then - list1[domain] = { - dns = {}, - ipsets = {} - } - end - for line in string.gmatch(ipset, '[^' .. "," .. ']+') do - if not check_ipset(domain, line) then - table.insert(list1[domain].ipsets, line) - end - end + if domain == "" or domain:find("#") then + return + end + if not ipset then + return + end + if not list1[domain] then + list1[domain] = { + dns = {}, + ipsets = {} + } + end + for line in string.gmatch(ipset, '[^' .. "," .. ']+') do + if not check_ipset(domain, line) then + table.insert(list1[domain].ipsets, line) + end + end end local function add_excluded_domain(domain) - if domain == "" or domain:find("#") then - return - end + if domain == "" or domain:find("#") then + return + end table.insert(excluded_domain, domain) - excluded_domain_str = excluded_domain_str .. "|" .. domain + excluded_domain_str = excluded_domain_str .. "|" .. domain end local function check_excluded_domain(domain) - if domain == "" or domain:find("#") then - return false - end + if domain == "" or domain:find("#") then + return false + end for k,v in ipairs(excluded_domain) do if domain:find(v) then return true end end - return false + return false end local cache_text = "" local new_rules = luci.sys.exec("echo -n $(find /usr/share/passwall/rules -type f | xargs md5sum)") local new_text = TMP_DNSMASQ_PATH .. DNSMASQ_CONF_FILE .. DEFAULT_DNS .. LOCAL_DNS .. TUN_DNS .. REMOTE_FAKEDNS .. CHNROUTE_MODE_DEFAULT_DNS .. CHINADNS_DNS .. PROXY_MODE .. NO_PROXY_IPV6 .. new_rules .. NFTFLAG if fs.access(CACHE_TEXT_FILE) then - for line in io.lines(CACHE_TEXT_FILE) do - cache_text = line - end + for line in io.lines(CACHE_TEXT_FILE) do + cache_text = line + end end if cache_text ~= new_text then - api.remove(CACHE_DNS_PATH .. "*") + api.remove(CACHE_DNS_PATH .. "*") end local global = PROXY_MODE:find("global") @@ -170,252 +170,252 @@ local only_global local dnsmasq_default_dns if CHNROUTE_MODE_DEFAULT_DNS ~= "nil" and chnlist then - if CHNROUTE_MODE_DEFAULT_DNS == "remote" then - dnsmasq_default_dns = TUN_DNS - end - if CHNROUTE_MODE_DEFAULT_DNS == "chinadns_ng" and CHINADNS_DNS ~= "0" then - dnsmasq_default_dns = CHINADNS_DNS - end + if CHNROUTE_MODE_DEFAULT_DNS == "remote" then + dnsmasq_default_dns = TUN_DNS + end + if CHNROUTE_MODE_DEFAULT_DNS == "chinadns_ng" and CHINADNS_DNS ~= "0" then + dnsmasq_default_dns = CHINADNS_DNS + end end if global and (not returnhome and not chnlist and not gfwlist) then - --只有全局模式时 - dnsmasq_default_dns = TUN_DNS - only_global = 1 + --只有全局模式时 + dnsmasq_default_dns = TUN_DNS + only_global = 1 end local setflag_4= (NFTFLAG == "1") and "4#inet#fw4#" or "" local setflag_6= (NFTFLAG == "1") and "6#inet#fw4#" or "" if not fs.access(CACHE_DNS_PATH) then - fs.mkdir("/tmp/dnsmasq.d") - fs.mkdir(CACHE_DNS_PATH) + fs.mkdir("/tmp/dnsmasq.d") + fs.mkdir(CACHE_DNS_PATH) - --屏蔽列表 - for line in io.lines("/usr/share/passwall/rules/block_host") do - if line ~= "" and not line:find("#") then - set_domain_address(line, "0.0.0.0") - end - end + --屏蔽列表 + for line in io.lines("/usr/share/passwall/rules/block_host") do + if line ~= "" and not line:find("#") then + set_domain_address(line, "0.0.0.0") + end + end - --始终用国内DNS解析节点域名 - uci:foreach(appname, "nodes", function(t) - local address = t.address - if datatypes.hostname(address) then - set_domain_dns(address, LOCAL_DNS) - set_domain_ipset(address, setflag_4 .. "vpsiplist," .. setflag_6 .. "vpsiplist6") - end - end) - log(string.format(" - 节点列表中的域名(vpsiplist):%s", LOCAL_DNS or "默认")) + --始终用国内DNS解析节点域名 + uci:foreach(appname, "nodes", function(t) + local address = t.address + if datatypes.hostname(address) then + set_domain_dns(address, LOCAL_DNS) + set_domain_ipset(address, setflag_4 .. "vpsiplist," .. setflag_6 .. "vpsiplist6") + end + end) + log(string.format(" - 节点列表中的域名(vpsiplist):%s", LOCAL_DNS or "默认")) - --始终用国内DNS解析直连(白名单)列表 - for line in io.lines("/usr/share/passwall/rules/direct_host") do - if line ~= "" and not line:find("#") then - add_excluded_domain(line) - set_domain_dns(line, LOCAL_DNS) - set_domain_ipset(line, setflag_4 .. "whitelist," .. setflag_6 .. "whitelist6") - end - end - log(string.format(" - 域名白名单(whitelist):%s", LOCAL_DNS or "默认")) + --始终用国内DNS解析直连(白名单)列表 + for line in io.lines("/usr/share/passwall/rules/direct_host") do + if line ~= "" and not line:find("#") then + add_excluded_domain(line) + set_domain_dns(line, LOCAL_DNS) + set_domain_ipset(line, setflag_4 .. "whitelist," .. setflag_6 .. "whitelist6") + end + end + log(string.format(" - 域名白名单(whitelist):%s", LOCAL_DNS or "默认")) - local fwd_dns - local ipset_flag - local no_ipv6 + local fwd_dns + local ipset_flag + local no_ipv6 - --始终使用远程DNS解析代理(黑名单)列表 - for line in io.lines("/usr/share/passwall/rules/proxy_host") do - if line ~= "" and not line:find("#") then - add_excluded_domain(line) - local ipset_flag = setflag_4 .. "blacklist," .. setflag_6 .. "blacklist6" - if NO_PROXY_IPV6 == "1" then - set_domain_address(line, "::") - ipset_flag = setflag_4 .. "blacklist" - end - if REMOTE_FAKEDNS == "1" then - ipset_flag = nil - end - set_domain_dns(line, TUN_DNS) - set_domain_ipset(line, ipset_flag) - end - end - log(string.format(" - 代理域名表(blacklist):%s", TUN_DNS or "默认")) + --始终使用远程DNS解析代理(黑名单)列表 + for line in io.lines("/usr/share/passwall/rules/proxy_host") do + if line ~= "" and not line:find("#") then + add_excluded_domain(line) + local ipset_flag = setflag_4 .. "blacklist," .. setflag_6 .. "blacklist6" + if NO_PROXY_IPV6 == "1" then + set_domain_address(line, "::") + ipset_flag = setflag_4 .. "blacklist" + end + if REMOTE_FAKEDNS == "1" then + ipset_flag = nil + end + set_domain_dns(line, TUN_DNS) + set_domain_ipset(line, ipset_flag) + end + end + log(string.format(" - 代理域名表(blacklist):%s", TUN_DNS or "默认")) - --分流规则 - if uci:get(appname, TCP_NODE, "protocol") == "_shunt" then - local t = uci:get_all(appname, TCP_NODE) - local default_node_id = t["default_node"] or "_direct" - uci:foreach(appname, "shunt_rules", function(s) - local _node_id = t[s[".name"]] or "nil" - if _node_id ~= "nil" and _node_id ~= "_blackhole" then - if _node_id == "_default" then - _node_id = default_node_id - end + --分流规则 + if uci:get(appname, TCP_NODE, "protocol") == "_shunt" then + local t = uci:get_all(appname, TCP_NODE) + local default_node_id = t["default_node"] or "_direct" + uci:foreach(appname, "shunt_rules", function(s) + local _node_id = t[s[".name"]] or "nil" + if _node_id ~= "nil" and _node_id ~= "_blackhole" then + if _node_id == "_default" then + _node_id = default_node_id + end - fwd_dns = nil - ipset_flag = nil - no_ipv6 = nil + fwd_dns = nil + ipset_flag = nil + no_ipv6 = nil - if _node_id == "_direct" then - fwd_dns = LOCAL_DNS - ipset_flag = setflag_4 .. "whitelist," .. setflag_6 .. "whitelist6" - else - fwd_dns = TUN_DNS - ipset_flag = setflag_4 .. "shuntlist," .. setflag_6 .. "shuntlist6" - if NO_PROXY_IPV6 == "1" then - ipset_flag = setflag_4 .. "shuntlist" - no_ipv6 = true - end - if not only_global then - if REMOTE_FAKEDNS == "1" then - ipset_flag = nil - end - end - end + if _node_id == "_direct" then + fwd_dns = LOCAL_DNS + ipset_flag = setflag_4 .. "whitelist," .. setflag_6 .. "whitelist6" + else + fwd_dns = TUN_DNS + ipset_flag = setflag_4 .. "shuntlist," .. setflag_6 .. "shuntlist6" + if NO_PROXY_IPV6 == "1" then + ipset_flag = setflag_4 .. "shuntlist" + no_ipv6 = true + end + if not only_global then + if REMOTE_FAKEDNS == "1" then + ipset_flag = nil + end + end + end - local domain_list = s.domain_list or "" - for line in string.gmatch(domain_list, "[^\r\n]+") do - if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("geosite:") and not line:find("ext:") then - if line:find("domain:") or line:find("full:") then - line = string.match(line, ":([^:]+)$") - end - add_excluded_domain(line) - - if no_ipv6 then - set_domain_address(line, "::") - end - set_domain_dns(line, fwd_dns) - set_domain_ipset(line, ipset_flag) - end - end - if _node_id ~= "_direct" then - log(string.format(" - V2ray/Xray分流规则(%s):%s", s.remarks, fwd_dns or "默认")) - end - end - end) - end + local domain_list = s.domain_list or "" + for line in string.gmatch(domain_list, "[^\r\n]+") do + if line ~= "" and not line:find("#") and not line:find("regexp:") and not line:find("geosite:") and not line:find("ext:") then + if line:find("domain:") or line:find("full:") then + line = string.match(line, ":([^:]+)$") + end + add_excluded_domain(line) - --如果没有使用回国模式 - if not returnhome then - if fs.access("/usr/share/passwall/rules/gfwlist") then - local gfwlist_str = sys.exec('cat /usr/share/passwall/rules/gfwlist | grep -v -E "^#" | grep -v -E "' .. excluded_domain_str .. '"') - for line in string.gmatch(gfwlist_str, "[^\r\n]+") do - if line ~= "" then - local ipset_flag = setflag_4 .. "gfwlist," .. setflag_6 .. "gfwlist6" - if NO_PROXY_IPV6 == "1" then - ipset_flag = setflag_4 .. "gfwlist" - set_domain_address(line, "::") - end - if not only_global then - fwd_dns = TUN_DNS - if CHNROUTE_MODE_DEFAULT_DNS == "chinadns_ng" and CHINADNS_DNS ~= "0" then - fwd_dns = nil - end - if REMOTE_FAKEDNS == "1" then - ipset_flag = nil - end - set_domain_dns(line, fwd_dns) - set_domain_ipset(line, ipset_flag) - end - end - end - log(string.format(" - 防火墙域名表(gfwlist):%s", fwd_dns or "默认")) - end + if no_ipv6 then + set_domain_address(line, "::") + end + set_domain_dns(line, fwd_dns) + set_domain_ipset(line, ipset_flag) + end + end + if _node_id ~= "_direct" then + log(string.format(" - V2ray/Xray分流规则(%s):%s", s.remarks, fwd_dns or "默认")) + end + end + end) + end - if chnlist and fs.access("/usr/share/passwall/rules/chnlist") and (CHNROUTE_MODE_DEFAULT_DNS == "remote" or (CHNROUTE_MODE_DEFAULT_DNS == "chinadns_ng" and CHINADNS_DNS ~= "0")) then - fwd_dns = LOCAL_DNS - local chnlist_str = sys.exec('cat /usr/share/passwall/rules/chnlist | grep -v -E "^#" | grep -v -E "' .. excluded_domain_str .. '"') - for line in string.gmatch(chnlist_str, "[^\r\n]+") do - if line ~= "" then - if CHNROUTE_MODE_DEFAULT_DNS == "chinadns_ng" and CHINADNS_DNS ~= "0" then - fwd_dns = nil - end - set_domain_dns(line, fwd_dns) - set_domain_ipset(line, setflag_4 .. "chnroute," .. setflag_6 .. "chnroute6") - end - end - log(string.format(" - 中国域名表(chnroute):%s", fwd_dns or "默认")) - end - else - if fs.access("/usr/share/passwall/rules/chnlist") then - local chnlist_str = sys.exec('cat /usr/share/passwall/rules/chnlist | grep -v -E "^#" | grep -v -E "' .. excluded_domain_str .. '"') - for line in string.gmatch(chnlist_str, "[^\r\n]+") do - if line ~= "" then - local ipset_flag = setflag_4 .. "chnroute," .. setflag_6 .. "chnroute6" - if NO_PROXY_IPV6 == "1" then - ipset_flag = setflag_4 .. "chnroute" - set_domain_address(line, "::") - end - if not only_global then - set_domain_dns(line, TUN_DNS) - if REMOTE_FAKEDNS == "1" then - ipset_flag = nil - end - set_domain_ipset(line, ipset_flag) - end - end - end - log(string.format(" - 中国域名表(chnroute):%s", TUN_DNS or "默认")) - end - end + --如果没有使用回国模式 + if not returnhome then + if fs.access("/usr/share/passwall/rules/gfwlist") then + local gfwlist_str = sys.exec('cat /usr/share/passwall/rules/gfwlist | grep -v -E "^#" | grep -v -E "' .. excluded_domain_str .. '"') + for line in string.gmatch(gfwlist_str, "[^\r\n]+") do + if line ~= "" then + local ipset_flag = setflag_4 .. "gfwlist," .. setflag_6 .. "gfwlist6" + if NO_PROXY_IPV6 == "1" then + ipset_flag = setflag_4 .. "gfwlist" + set_domain_address(line, "::") + end + if not only_global then + fwd_dns = TUN_DNS + if CHNROUTE_MODE_DEFAULT_DNS == "chinadns_ng" and CHINADNS_DNS ~= "0" then + fwd_dns = nil + end + if REMOTE_FAKEDNS == "1" then + ipset_flag = nil + end + set_domain_dns(line, fwd_dns) + set_domain_ipset(line, ipset_flag) + end + end + end + log(string.format(" - 防火墙域名表(gfwlist):%s", fwd_dns or "默认")) + end - local address_out = io.open(CACHE_DNS_PATH .. "/000-address.conf", "a") - local server_out = io.open(CACHE_DNS_PATH .. "/001-server.conf", "a") - local ipset_out = io.open(CACHE_DNS_PATH .. "/ipset.conf", "a") - local set_name = "ipset" - if NFTFLAG == "1" then - set_name = "nftset" - end - for key, value in pairs(list1) do - if value.address and #value.address > 0 then - address_out:write(string.format("address=/.%s/%s\n", key, value.address)) - end - if value.dns and #value.dns > 0 then - for i, dns in ipairs(value.dns) do - server_out:write(string.format("server=/.%s/%s\n", key, dns)) - end - end - if value.ipsets and #value.ipsets > 0 then - local ipsets_str = "" - for i, ipset in ipairs(value.ipsets) do - ipsets_str = ipsets_str .. ipset .. "," - end - ipsets_str = ipsets_str:sub(1, #ipsets_str - 1) - ipset_out:write(string.format("%s=/.%s/%s\n", set_name, key, ipsets_str)) - end - end - address_out:close() - server_out:close() - ipset_out:close() + if chnlist and fs.access("/usr/share/passwall/rules/chnlist") and (CHNROUTE_MODE_DEFAULT_DNS == "remote" or (CHNROUTE_MODE_DEFAULT_DNS == "chinadns_ng" and CHINADNS_DNS ~= "0")) then + fwd_dns = LOCAL_DNS + local chnlist_str = sys.exec('cat /usr/share/passwall/rules/chnlist | grep -v -E "^#" | grep -v -E "' .. excluded_domain_str .. '"') + for line in string.gmatch(chnlist_str, "[^\r\n]+") do + if line ~= "" then + if CHNROUTE_MODE_DEFAULT_DNS == "chinadns_ng" and CHINADNS_DNS ~= "0" then + fwd_dns = nil + end + set_domain_dns(line, fwd_dns) + set_domain_ipset(line, setflag_4 .. "chnroute," .. setflag_6 .. "chnroute6") + end + end + log(string.format(" - 中国域名表(chnroute):%s", fwd_dns or "默认")) + end + else + if fs.access("/usr/share/passwall/rules/chnlist") then + local chnlist_str = sys.exec('cat /usr/share/passwall/rules/chnlist | grep -v -E "^#" | grep -v -E "' .. excluded_domain_str .. '"') + for line in string.gmatch(chnlist_str, "[^\r\n]+") do + if line ~= "" then + local ipset_flag = setflag_4 .. "chnroute," .. setflag_6 .. "chnroute6" + if NO_PROXY_IPV6 == "1" then + ipset_flag = setflag_4 .. "chnroute" + set_domain_address(line, "::") + end + if not only_global then + set_domain_dns(line, TUN_DNS) + if REMOTE_FAKEDNS == "1" then + ipset_flag = nil + end + set_domain_ipset(line, ipset_flag) + end + end + end + log(string.format(" - 中国域名表(chnroute):%s", TUN_DNS or "默认")) + end + end - local f_out = io.open(CACHE_TEXT_FILE, "a") - f_out:write(new_text) - f_out:close() + local address_out = io.open(CACHE_DNS_PATH .. "/000-address.conf", "a") + local server_out = io.open(CACHE_DNS_PATH .. "/001-server.conf", "a") + local ipset_out = io.open(CACHE_DNS_PATH .. "/ipset.conf", "a") + local set_name = "ipset" + if NFTFLAG == "1" then + set_name = "nftset" + end + for key, value in pairs(list1) do + if value.address and #value.address > 0 then + address_out:write(string.format("address=/.%s/%s\n", key, value.address)) + end + if value.dns and #value.dns > 0 then + for i, dns in ipairs(value.dns) do + server_out:write(string.format("server=/.%s/%s\n", key, dns)) + end + end + if value.ipsets and #value.ipsets > 0 then + local ipsets_str = "" + for i, ipset in ipairs(value.ipsets) do + ipsets_str = ipsets_str .. ipset .. "," + end + ipsets_str = ipsets_str:sub(1, #ipsets_str - 1) + ipset_out:write(string.format("%s=/.%s/%s\n", set_name, key, ipsets_str)) + end + end + address_out:close() + server_out:close() + ipset_out:close() + + local f_out = io.open(CACHE_TEXT_FILE, "a") + f_out:write(new_text) + f_out:close() end if api.is_install("procd\\-ujail") then - fs.copyr(CACHE_DNS_PATH, TMP_DNSMASQ_PATH) + fs.copyr(CACHE_DNS_PATH, TMP_DNSMASQ_PATH) else - api.remove(TMP_DNSMASQ_PATH) - fs.symlink(CACHE_DNS_PATH, TMP_DNSMASQ_PATH) + api.remove(TMP_DNSMASQ_PATH) + fs.symlink(CACHE_DNS_PATH, TMP_DNSMASQ_PATH) end if DNSMASQ_CONF_FILE ~= "nil" then - local conf_out = io.open(DNSMASQ_CONF_FILE, "a") - conf_out:write(string.format("conf-dir=%s\n", TMP_DNSMASQ_PATH)) - if dnsmasq_default_dns then - conf_out:write(string.format("server=%s\n", dnsmasq_default_dns)) - conf_out:write("all-servers\n") - conf_out:write("no-poll\n") - conf_out:write("no-resolv\n") - conf_out:close() - log(string.format(" - 以上所列以外及默认:%s", dnsmasq_default_dns)) + local conf_out = io.open(DNSMASQ_CONF_FILE, "a") + conf_out:write(string.format("conf-dir=%s\n", TMP_DNSMASQ_PATH)) + if dnsmasq_default_dns then + conf_out:write(string.format("server=%s\n", dnsmasq_default_dns)) + conf_out:write("all-servers\n") + conf_out:write("no-poll\n") + conf_out:write("no-resolv\n") + conf_out:close() + log(string.format(" - 以上所列以外及默认:%s", dnsmasq_default_dns)) - if FLAG == "default" then - local f_out = io.open("/tmp/etc/passwall/default_DNS", "a") - f_out:write(DEFAULT_DNS) - f_out:close() - end - end + if FLAG == "default" then + local f_out = io.open("/tmp/etc/passwall/default_DNS", "a") + f_out:write(DEFAULT_DNS) + f_out:close() + end + end end log(" - PassWall必须依赖于Dnsmasq,如果你自行配置了错误的DNS流程,将会导致域名(直连/代理域名)分流失效!!!") diff --git a/luci-app-passwall/root/usr/share/passwall/rule_update.lua b/luci-app-passwall/root/usr/share/passwall/rule_update.lua index c06cdd026..67b5cc3b0 100755 --- a/luci-app-passwall/root/usr/share/passwall/rule_update.lua +++ b/luci-app-passwall/root/usr/share/passwall/rule_update.lua @@ -35,18 +35,18 @@ local geosite_api = "https://api.github.com/repos/Loyalsoldier/v2ray-rules-dat/ local v2ray_asset_location = ucic:get_first(name, 'global_rules', "v2ray_location_asset", "/usr/share/v2ray/") local log = function(...) - if arg1 then - local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") - if arg1 == "log" then - local f, err = io.open("/tmp/log/passwall.log", "a") - if f and err == nil then - f:write(result .. "\n") - f:close() - end - elseif arg1 == "print" then - print(result) - end - end + if arg1 then + local result = os.date("%Y-%m-%d %H:%M:%S: ") .. table.concat({...}, " ") + if arg1 == "log" then + local f, err = io.open("/tmp/log/passwall.log", "a") + if f and err == nil then + f:write(result .. "\n") + f:close() + end + elseif arg1 == "print" then + print(result) + end + end end -- curl