diff --git a/luci-app-passwall/Makefile b/luci-app-passwall/Makefile index ffee7c6c7..85955cc92 100644 --- a/luci-app-passwall/Makefile +++ b/luci-app-passwall/Makefile @@ -6,7 +6,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall -PKG_VERSION:=4.71-3 +PKG_VERSION:=4.72-1 PKG_RELEASE:= PKG_CONFIG_DEPENDS:= \ diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua index 5024e871c..7d6ebf8bf 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe.lua @@ -6,27 +6,46 @@ local has_trojan_plus = api.is_finded("trojan-plus") local has_singbox = api.finded_com("singbox") local has_xray = api.finded_com("xray") local has_trojan_go = api.finded_com("trojan-go") +local has_hysteria2 = api.finded_com("hysteria") local ss_aead_type = {} local trojan_type = {} +local vmess_type = {} +local vless_type = {} +local hysteria2_type = {} if has_ss then - ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev" + local s = "shadowsocks-libev" + table.insert(ss_aead_type, s) end if has_ss_rust then - ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" + local s = "shadowsocks-rust" + table.insert(ss_aead_type, s) end if has_trojan_plus then - trojan_type[#trojan_type + 1] = "trojan-plus" + local s = "trojan-plus" + table.insert(trojan_type, s) end if has_singbox then - trojan_type[#trojan_type + 1] = "sing-box" - ss_aead_type[#ss_aead_type + 1] = "sing-box" + local s = "sing-box" + table.insert(trojan_type, s) + table.insert(ss_aead_type, s) + table.insert(vmess_type, s) + table.insert(vless_type, s) + table.insert(hysteria2_type, s) end if has_xray then - trojan_type[#trojan_type + 1] = "xray" - ss_aead_type[#ss_aead_type + 1] = "xray" + local s = "xray" + table.insert(trojan_type, s) + table.insert(ss_aead_type, s) + table.insert(vmess_type, s) + table.insert(vless_type, s) end if has_trojan_go then - trojan_type[#trojan_type + 1] = "trojan-go" + local s = "trojan-go" + table.insert(trojan_type, s) +end +if has_hysteria2 then + local s = "hysteria2" + table.insert(hysteria2_type, s) end m = Map(appname) @@ -48,16 +67,46 @@ o = s:option(DynamicList, "filter_discard_list", translate("Discard List")) o = s:option(DynamicList, "filter_keep_list", translate("Keep List")) if #ss_aead_type > 0 then - o = s:option(ListValue, "ss_aead_type", translate("SS AEAD Node Use Type")) + o = s:option(ListValue, "ss_aead_type", translatef("%s Node Use Type", "SS AEAD")) for key, value in pairs(ss_aead_type) do - o:value(value, translate(value:gsub("^%l",string.upper))) + o:value(value) end end if #trojan_type > 0 then - o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) + o = s:option(ListValue, "trojan_type", translatef("%s Node Use Type", "Trojan")) for key, value in pairs(trojan_type) do - o:value(value, translate(value:gsub("^%l",string.upper))) + o:value(value) + end +end + +if #vmess_type > 0 then + o = s:option(ListValue, "vmess_type", translatef("%s Node Use Type", "VMess")) + for key, value in pairs(vmess_type) do + o:value(value) + end + if has_xray then + o.default = "xray" + end +end + +if #vless_type > 0 then + o = s:option(ListValue, "vless_type", translatef("%s Node Use Type", "VLESS")) + for key, value in pairs(vless_type) do + o:value(value) + end + if has_xray then + o.default = "xray" + end +end + +if #hysteria2_type > 0 then + o = s:option(ListValue, "hysteria2_type", translatef("%s Node Use Type", "Hysteria2")) + for key, value in pairs(hysteria2_type) do + o:value(value) + end + if has_hysteria2 then + o.default = "hysteria2" end end 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 203f2e5ea..53ff9535d 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 @@ -1,33 +1,51 @@ local api = require "luci.passwall.api" local appname = api.appname -local sys = api.sys local has_ss = api.is_finded("ss-redir") local has_ss_rust = api.is_finded("sslocal") local has_trojan_plus = api.is_finded("trojan-plus") local has_singbox = api.finded_com("singbox") local has_xray = api.finded_com("xray") local has_trojan_go = api.finded_com("trojan-go") +local has_hysteria2 = api.finded_com("hysteria") local ss_aead_type = {} local trojan_type = {} +local vmess_type = {} +local vless_type = {} +local hysteria2_type = {} if has_ss then - ss_aead_type[#ss_aead_type + 1] = "shadowsocks-libev" + local s = "shadowsocks-libev" + table.insert(ss_aead_type, s) end if has_ss_rust then - ss_aead_type[#ss_aead_type + 1] = "shadowsocks-rust" + local s = "shadowsocks-rust" + table.insert(ss_aead_type, s) end if has_trojan_plus then - trojan_type[#trojan_type + 1] = "trojan-plus" + local s = "trojan-plus" + table.insert(trojan_type, s) end if has_singbox then - trojan_type[#trojan_type + 1] = "sing-box" - ss_aead_type[#ss_aead_type + 1] = "sing-box" + local s = "sing-box" + table.insert(trojan_type, s) + table.insert(ss_aead_type, s) + table.insert(vmess_type, s) + table.insert(vless_type, s) + table.insert(hysteria2_type, s) end if has_xray then - trojan_type[#trojan_type + 1] = "xray" - ss_aead_type[#ss_aead_type + 1] = "xray" + local s = "xray" + table.insert(trojan_type, s) + table.insert(ss_aead_type, s) + table.insert(vmess_type, s) + table.insert(vless_type, s) end if has_trojan_go then - trojan_type[#trojan_type + 1] = "trojan-go" + local s = "trojan-go" + table.insert(trojan_type, s) +end +if has_hysteria2 then + local s = "hysteria2" + table.insert(hysteria2_type, s) end m = Map(appname) @@ -69,20 +87,47 @@ 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 = s:option(ListValue, "ss_aead_type", translatef("%s Node Use Type", "SS AEAD")) 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))) + o:value(value) end end if #trojan_type > 0 then - o = s:option(ListValue, "trojan_type", translate("Trojan Node Use Type")) + o = s:option(ListValue, "trojan_type", translatef("%s Node Use Type", "Trojan")) 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))) + o:value(value) + end +end + +if #vmess_type > 0 then + o = s:option(ListValue, "vmess_type", translatef("%s Node Use Type", "VMess")) + o.default = "global" + o:value("global", translate("Use global config")) + for key, value in pairs(vmess_type) do + o:value(value) + end +end + +if #vless_type > 0 then + o = s:option(ListValue, "vless_type", translatef("%s Node Use Type", "VLESS")) + o.default = "global" + o:value("global", translate("Use global config")) + for key, value in pairs(vless_type) do + o:value(value) + end +end + +if #hysteria2_type > 0 then + o = s:option(ListValue, "hysteria2_type", translatef("%s Node Use Type", "Hysteria2")) + o.default = "global" + o:value("global", translate("Use global config")) + for key, value in pairs(hysteria2_type) do + o:value(value) end end 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 881ba29cf..1ceb9e821 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/other.lua @@ -200,6 +200,20 @@ if has_singbox then o.default = "https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db" o:value("https://github.com/SagerNet/sing-geosite/releases/latest/download/geosite.db") o.rmempty = false + + o = s:option(Button, "_remove_resource", translate("Remove resource files")) + o.description = translate("Sing-Box will automatically download resource files when starting, you can use this feature achieve upgrade resource files.") + o.inputstyle = "remove" + function o.write(self, section, value) + local geoip_path = s.fields["geoip_path"] and s.fields["geoip_path"]:formvalue(section) or nil + if geoip_path then + os.remove(geoip_path) + end + local geosite_path = s.fields["geosite_path"] and s.fields["geosite_path"]:formvalue(section) or nil + if geosite_path then + os.remove(geosite_path) + end + end 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 a4c0be587..d936711b7 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 @@ -19,6 +19,87 @@ protocol:value("http") protocol:value("tls") protocol:value("bittorrent") +o = s:option(MultiValue, "inbound", translate("Inbound Tag")) +o:value("tproxy", translate("Transparent proxy")) +o:value("socks", "Socks") + +network = s:option(ListValue, "network", translate("Network")) +network:value("tcp,udp", "TCP UDP") +network:value("tcp", "TCP") +network:value("udp", "UDP") + +source = s:option(DynamicList, "source", translate("Source")) +source.description = "" +source.cast = "string" +source.cfgvalue = function(self, section) + 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 + end + return value +end +source.validate = function(self, value, t) + local err = {} + for _, v in ipairs(value) do + local flag = false + if datatypes.ip4addr(v) then + flag = true + end + + if flag == false and v:find("geoip:") and v:find("geoip:") == 1 then + flag = true + 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 + + return value +end + +local dynamicList_write = function(self, section, value) + 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 + end + end + else + t = { value } + end + t = table.concat(t, " ") + return DynamicList.write(self, section, t) +end + +source.write = dynamicList_write + +port = s:option(Value, "port", translate("port")) + domain_list = s:option(TextValue, "domain_list", translate("Domain")) domain_list.rows = 10 domain_list.wrap = "off" diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/socks_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/socks_config.lua index 14b096619..be67a87be 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/socks_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/socks_config.lua @@ -108,10 +108,8 @@ o.default = "https://www.google.com/generate_204" o:depends("enable_autoswitch", true) for k, v in pairs(nodes_table) do - if v.node_type == "normal" then - autoswitch_backup_node:value(v.id, v["remark"]) - socks_node:value(v.id, v["remark"]) - end + autoswitch_backup_node:value(v.id, v["remark"]) + socks_node:value(v.id, v["remark"]) end m:append(Template(appname .. "/socks_auto_switch/footer")) diff --git a/luci-app-passwall/luasrc/passwall/util_sing-box.lua b/luci-app-passwall/luasrc/passwall/util_sing-box.lua index e49ec9946..5f2eb04b3 100644 --- a/luci-app-passwall/luasrc/passwall/util_sing-box.lua +++ b/luci-app-passwall/luasrc/passwall/util_sing-box.lua @@ -1052,8 +1052,31 @@ function gen_config(var) table.insert(protocols, w) end) end + + local inboundTag = nil + if e["inbound"] and e["inbound"] ~= "" then + inboundTag = {} + if e["inbound"]:find("tproxy") then + if tcp_redir_port then + if tcp_proxy_way == "tproxy" then + table.insert(inboundTag, "tproxy_tcp") + else + table.insert(inboundTag, "redirect_tcp") + end + end + if udp_redir_port then + table.insert(inboundTag, "tproxy_udp") + end + end + if e["inbound"]:find("socks") then + if local_socks_port then + table.insert(inboundTag, "socks-in") + end + end + end local rule = { + inbound = inboundTag, outbound = outboundTag, invert = false, --匹配反选 protocol = protocols diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index b98cd94f3..9f1abdd3f 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -547,6 +547,7 @@ function gen_config(var) local node = uci:get_all(appname, node_id) if local_socks_port then local inbound = { + tag = "socks-in", listen = local_socks_address, port = tonumber(local_socks_port), protocol = "socks", @@ -870,39 +871,70 @@ function gen_config(var) table.insert(protocols, w) end) end + local inboundTag = nil + if e["inbound"] and e["inbound"] ~= "" then + inboundTag = {} + if e["inbound"]:find("tproxy") then + if tcp_redir_port then + table.insert(inboundTag, "tcp_redir") + end + if udp_redir_port then + table.insert(inboundTag, "udp_redir") + end + end + if e["inbound"]:find("socks") then + if local_socks_port then + table.insert(inboundTag, "socks-in") + end + end + end + local domains = nil if e.domain_list then - local _domain = {} + domains = {} string.gsub(e.domain_list, '[^' .. "\r\n" .. ']+', function(w) - table.insert(_domain, w) + table.insert(domains, w) end) - table.insert(rules, { - type = "field", - outboundTag = outboundTag, - balancerTag = balancerTag, - domain = _domain, - protocol = protocols - }) end + local ip = nil if e.ip_list then - local _ip = {} + ip = {} string.gsub(e.ip_list, '[^' .. "\r\n" .. ']+', function(w) - table.insert(_ip, w) + table.insert(ip, w) end) - table.insert(rules, { - type = "field", - outboundTag = outboundTag, - balancerTag = balancerTag, - 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, - balancerTag = balancerTag, - protocol = protocols - }) + local source = nil + if e.source then + source = {} + string.gsub(e.source, '[^' .. " " .. ']+', function(w) + table.insert(source, w) + end) + end + local rule = { + _flag = e.remarks, + type = "field", + inboundTag = inboundTag, + outboundTag = outboundTag, + balancerTag = balancerTag, + network = e["network"] or "tcp,udp", + source = source, + sourcePort = nil, + port = e["port"] ~= "" and e["port"] or nil, + protocol = protocols + } + if domains then + local _rule = api.clone(rule) + _rule["_flag"] = _rule["_flag"] .. "_domains" + _rule.domains = domains + table.insert(rules, _rule) + end + if ip then + local _rule = api.clone(rule) + _rule["_flag"] = _rule["_flag"] .. "_ip" + _rule.ip = ip + table.insert(rules, _rule) + end + if not domains and not ip and protocols then + table.insert(rules, rule) end end end) 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 8e78f726f..12fdebe6b 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 @@ -5,6 +5,7 @@ local api = require "luci.passwall.api"