diff --git a/package/lienol/luci-app-passwall/Makefile b/package/lienol/luci-app-passwall/Makefile index 81dbc80417..ec7eb8fd24 100644 --- a/package/lienol/luci-app-passwall/Makefile +++ b/package/lienol/luci-app-passwall/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=4 -PKG_RELEASE:=14 -PKG_DATE:=20210209 +PKG_RELEASE:=15 +PKG_DATE:=20210213 PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)-$(PKG_VERSION) @@ -101,6 +101,7 @@ define Package/$(PKG_NAME) +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR:shadowsocksr-libev-ssr-local \ +PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Server:shadowsocksr-libev-ssr-server \ +PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-core \ + +PACKAGE_$(PKG_NAME)_INCLUDE_Xray:xray-geodata \ +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_Plus:trojan-plus \ +PACKAGE_$(PKG_NAME)_INCLUDE_Trojan_GO:trojan-go \ +PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy:naiveproxy \ diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua index 593c9cdf64..4b044ef385 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/api.lua @@ -162,6 +162,24 @@ 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 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 res = {} + copy(org, res) + return res +end + function get_xray_path() local path = uci_get_type("global_app", "xray_file") return path diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua index 2c124ab5f4..6052b597d9 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/api/gen_xray.lua @@ -25,7 +25,7 @@ local new_port local ucursor = require"luci.model.uci".cursor() local sys = require "luci.sys" local json = require "luci.jsonc" -local appname = "passwall" +local appname = api.appname local dns = nil local inbounds = {} local outbounds = {} @@ -40,31 +40,48 @@ local function get_new_port() return new_port end -function gen_outbound(node, tag, relay_port) +function gen_outbound(node, tag, is_proxy) local result = nil - if node then + if node and node ~= "nil" then local node_id = node[".name"] if tag == nil then tag = node_id end + + if is_proxy and is_proxy == "1" then + new_port = get_new_port() + table.insert(inbounds, { + tag = "proxy_" .. tag, + 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 + end + if node.type ~= "Xray" and node.type ~= "V2ray" then if node.type == "Socks" then node.protocol = "socks" node.transport = "tcp" else local node_type = proto or "socks" + local relay_port = node.port new_port = get_new_port() node.port = new_port - sys.call(string.format('/usr/share/%s/app.sh run_socks "%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s"> /dev/null', - appname, - new_port, - node_id, - "127.0.0.1", - new_port, - string.format("/var/etc/%s/v2_%s_%s.json", appname, node_type, node_id), - "0", - "nil", - relay_port and tostring(relay_port) or "" + sys.call(string.format('/usr/share/%s/app.sh run_socks "%s" "%s" "%s" "%s" "%s" "%s" "%s" "%s"> /dev/null', appname, + new_port, --flag + node_id, --node + "127.0.0.1", --bind + new_port, --socks port + string.format("/var/etc/%s/v2_%s_%s_%s.json", appname, node_type, node_id, new_port), --config file + "0", --http port + "nil", -- http config file + (is_proxy and is_proxy == "1" and relay_port) and tostring(relay_port) or "" --relay port ) ) node.protocol = "socks" @@ -86,6 +103,8 @@ function gen_outbound(node, tag, relay_port) end result = { + _flag_tag = node_id, + _flag_is_proxy = (is_proxy and is_proxy == "1") and "1" or "0", tag = tag, protocol = node.protocol, mux = (node.stream_security ~= "xtls") and { @@ -222,11 +241,80 @@ if node_section then end end + local up_trust_doh = ucursor:get(appname, "@global[0]", "up_trust_doh") + if up_trust_doh then + local t = {} + string.gsub(up_trust_doh, '[^' .. "," .. ']+', function (w) + table.insert(t, w) + end) + if #t > 1 then + local host = sys.exec("echo -n $(echo " .. t[1] .. " | sed 's/https:\\/\\///g' | awk -F ':' '{print $1}' | awk -F '/' '{print $1}')") + dns = { + hosts = { + [host] = t[2] + } + } + end + end + if node.protocol == "_shunt" then local rules = {} + + local default_node_id = node.default_node or "_direct" + local outboundTag + if default_node_id == "_direct" then + outboundTag = "direct" + elseif default_node_id == "_blackhole" then + outboundTag = "blackhole" + else + local default_node = ucursor:get_all(appname, default_node_id) + local main_node_id = node.main_node or "nil" + if main_node_id ~= "nil" then + if main_node_id == default_node_id then + else + 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 + local node = ucursor:get_all(appname, main_node_id) + local outbound = gen_outbound(node, "main") + if outbound then + table.insert(outbounds, outbound) + table.insert(rules, 1, { + type = "field", + inboundTag = {"proxy_default"}, + outboundTag = "main" + }) + end + end + end + local default_outbound = gen_outbound(default_node, "default") + if default_outbound then + table.insert(outbounds, default_outbound) + outboundTag = "default" + end + end + if outboundTag then + table.insert(rules, { + type = "field", + outboundTag = outboundTag, + network = network + }) + end + ucursor:foreach(appname, "shunt_rules", function(e) local name = e[".name"] local _node_id = node[name] or "nil" + local is_proxy = node[name .. "_proxy"] or "0" local outboundTag if _node_id == "_direct" then outboundTag = "direct" @@ -234,36 +322,31 @@ if node_section then outboundTag = "blackhole" else if _node_id ~= "nil" then - local _node = ucursor:get_all(appname, _node_id) - local is_proxy = node[name .. "_proxy"] - local relay_port - if is_proxy and is_proxy == "1" then - new_port = get_new_port() - relay_port = 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 + local has_outbound + for index, value in ipairs(outbounds) do + if value["_flag_tag"] == _node_id and value["_flag_is_proxy"] == is_proxy then + has_outbound = api.clone(value) + break end - _node.address = "127.0.0.1" - _node.port = new_port end - local _outbound = gen_outbound(_node, name, relay_port) - if _outbound then - table.insert(outbounds, _outbound) - if is_proxy and is_proxy == "1" then - table.insert(rules, { - type = "field", - inboundTag = {"proxy_" .. name}, - outboundTag = "default" - }) - end + if has_outbound then + has_outbound["tag"] = name + table.insert(outbounds, has_outbound) outboundTag = name + else + local _node = ucursor:get_all(appname, _node_id) + local _outbound = gen_outbound(_node, name, is_proxy) + if _outbound then + if is_proxy == "1" then + table.insert(rules, 1, { + type = "field", + inboundTag = {"proxy_" .. name}, + outboundTag = "default" + }) + end + table.insert(outbounds, _outbound) + outboundTag = name + end end end end @@ -292,59 +375,10 @@ if node_section then end end end) - - local default_node_id = node.default_node or nil - if default_node_id and default_node_id ~= "nil" then - local default_node = ucursor:get_all(appname, default_node_id) - if "1" == node.default_proxy then - local node_id = node.main_node or nil - if node_id and node_id ~= "nil" then - if node_id == default_node_id then - else - 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 - local node = ucursor:get_all(appname, node_id) - local outbound = gen_outbound(node, "main") - if outbound then - table.insert(outbounds, outbound) - local rule = { - type = "field", - inboundTag = {"proxy_default"}, - outboundTag = "main" - } - table.insert(rules, rule) - end - end - end - end - local default_outbound = gen_outbound(default_node, "default") - if default_outbound then - table.insert(outbounds, default_outbound) - local rule = { - type = "field", - outboundTag = "default", - network = network - } - table.insert(rules, rule) - end - end - routing = { domainStrategy = node.domainStrategy or "AsIs", rules = rules } - elseif node.protocol == "_balancing" then if node.balancing_node then local nodes = node.balancing_node @@ -456,7 +490,14 @@ if inbounds or outbounds then table.insert(outbounds, { protocol = "freedom", tag = "direct", - settings = {domainStrategy = "UseIPv4"} + settings = { + domainStrategy = "UseIPv4" + }, + streamSettings = { + sockopt = { + mark = 255 + } + } }) table.insert(outbounds, { protocol = "blackhole", @@ -465,7 +506,7 @@ if inbounds or outbounds then local xray = { log = { - -- error = string.format("/var/etc/passwall/%s.log", node[".name"]), + -- error = string.format("/var/etc/%s/%s.log", appname, node[".name"]), loglevel = loglevel }, -- DNS diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua index ab048d5eeb..3161695663 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/auto_switch.lua @@ -3,10 +3,7 @@ local appname = api.appname local nodes_table = {} for k, e in ipairs(api.get_valid_nodes()) do - nodes_table[#nodes_table + 1] = { - id = e[".name"], - remarks = e.remarks_name - } + nodes_table[#nodes_table + 1] = e end m = Map(appname) @@ -26,7 +23,9 @@ o.default = "1" o = s:option(DynamicList, "tcp_node", "TCP " .. translate("List of backup nodes")) for k, v in pairs(nodes_table) do - o:value(v.id, v.remarks) + if v.node_type == "normal" then + o:value(v.id, v.remarks_name) + end end o = s:option(Flag, "restore_switch", "TCP " .. translate("Restore Switch"), translate("When detects main node is available, switch back to the main node.")) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua index 299a324956..3e7b721cbf 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/global.lua @@ -120,11 +120,11 @@ if has_xray and #nodes_table > 0 then local id = e[".name"] o = s:taboption("Main", ListValue, v.id .. "." .. id .. "_node", string.format('* %s', api.url("shunt_rules", id), translate(e.remarks))) o:depends("tcp_node", v.id) - o:value("nil", translate("Close")) + o:value("nil", translate("Default")) o:value("_direct", translate("Direct Connection")) o:value("_blackhole", translate("Blackhole")) - for k, v in pairs(normal_list) do - o:value(v.id, v.remarks_name) + for k1, v1 in pairs(normal_list) do + o:value(v1.id, v1.remarks_name) end o.cfgvalue = function(self, section) return m:get(v.id, id) or "nil" @@ -137,9 +137,10 @@ if has_xray and #nodes_table > 0 then local id = "default_node" o = s:taboption("Main", ListValue, v.id .. "." .. id, "* " .. translate("Default")) o:depends("tcp_node", v.id) - o:value("nil", translate("Close")) - for k, v in pairs(normal_list) do - o:value(v.id, v.remarks_name) + o:value("_direct", translate("Direct Connection")) + o:value("_blackhole", translate("Blackhole")) + for k1, v1 in pairs(normal_list) do + o:value(v1.id, v1.remarks_name) end o.cfgvalue = function(self, section) return m:get(v.id, id) or "nil" @@ -152,8 +153,8 @@ if has_xray and #nodes_table > 0 then o = s:taboption("Main", ListValue, v.id .. "." .. id, "* " .. translate("Default") .. translate("Preproxy")) o:depends("tcp_node", v.id) o:value("nil", translate("Close")) - for k, v in pairs(normal_list) do - o:value(v.id, v.remarks_name) + for k1, v1 in pairs(normal_list) do + o:value(v1.id, v1.remarks_name) end o.cfgvalue = function(self, section) return m:get(v.id, id) or "nil" @@ -274,7 +275,9 @@ o:depends({dns_mode = "pdnsd"}) 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("/etc/init.d/" .. appname .. " stop && /usr/share/" .. appname .. "/iptables.sh flush_ipset && /etc/init.d/" .. appname .. " restart") + luci.sys.call("/etc/init.d/" .. appname .. " stop") + luci.sys.call("/usr/share/" .. appname .. "/iptables.sh flush_ipset") + luci.sys.call("/etc/init.d/" .. appname .. " restart") end s:tab("Proxy", translate("Mode")) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua index 4f3c4b6f51..b8c933e995 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/node_config.lua @@ -129,7 +129,7 @@ balancing_node:depends("protocol", "_balancing") -- 分流 uci:foreach(appname, "shunt_rules", function(e) o = s:option(ListValue, e[".name"], string.format('* %s', api.url("shunt_rules", e[".name"]), translate(e.remarks))) - o:value("nil", translate("Close")) + o:value("nil", translate("Default")) o:value("_direct", translate("Direct Connection")) o:value("_blackhole", translate("Blackhole")) o:depends("protocol", "_shunt") @@ -153,17 +153,19 @@ end shunt_tips:depends("protocol", "_shunt") default_node = s:option(ListValue, "default_node", translate("Default") .. " " .. translate("Node")) -default_node:value("nil", translate("Close")) +default_node:value("_direct", translate("Direct Connection")) +default_node:value("_blackhole", translate("Blackhole")) for k, v in pairs(nodes_table) do default_node:value(v.id, v.remarks) end default_node:depends("protocol", "_shunt") -default_proxy = s:option(Flag, "default_proxy", translate("Default") .. translate("Node") .. translate("Preproxy"), translate("Use the under node for the transit.")) -default_proxy.default = 0 -default_proxy:depends("protocol", "_shunt") - -o = s:option(ListValue, "main_node", " ") -for k, v in pairs(nodes_table) do o:value(v.id, v.remarks) end -o:depends("default_proxy", "1") +if #nodes_table > 0 then + o = s:option(ListValue, "main_node", translate("Default") .. " " .. translate("Node") .. translate("Preproxy"), translate("Use this node proxy to forward 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 domainStrategy = s:option(ListValue, "domainStrategy", translate("Domain Strategy")) domainStrategy:value("AsIs") diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua index 5025bf5853..de2e63faa6 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/rule.lua @@ -28,6 +28,9 @@ o = s:option(Value, "chnroute6_url", translate("China IPv6s(chnroute6) Update UR o:value("https://ispip.clang.cn/all_cn_ipv6.txt", translate("Clang.CN.IPv6")) o.default = "https://ispip.clang.cn/all_cn_ipv6.txt" +----chnlist URL +o = s:option(DynamicList, "chnlist_url", translate("China List(Chnlist) Update URL")) + s:append(Template(appname .. "/rule/rule_version")) ---- Auto Update @@ -57,6 +60,7 @@ s = m:section(TypedSection, "shunt_rules", "Xray" .. translate("Shunt") .. trans 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) diff --git a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua index 4ddc363eda..94814bf8b9 100644 --- a/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua +++ b/package/lienol/luci-app-passwall/luasrc/model/cbi/passwall/client/shunt_rules.lua @@ -57,7 +57,7 @@ ip_list.validate = function(self, value) 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) then + if not (datatypes.ipmask4(ipmask) or datatypes.ipmask6(ipmask)) then return nil, ipmask .. " " .. translate("Not valid IP format, please re-enter!") end end diff --git a/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm b/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm index 4d8d9ba62a..f6cea0bfdd 100644 --- a/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm +++ b/package/lienol/luci-app-passwall/luasrc/view/passwall/rule/rule_version.htm @@ -5,6 +5,8 @@ local gfwlist_update = api.uci_get_type("global_rules", "gfwlist_update", "1") = local chnroute_update = api.uci_get_type("global_rules", "chnroute_update", "1") == "1" and "checked='checked'" or "" local chnroute6_update = api.uci_get_type("global_rules", "chnroute6_update", "1") == "1" and "checked='checked'" or "" local chnlist_update = api.uci_get_type("global_rules", "chnlist_update", "1") == "1" and "checked='checked'" or "" +local geoip_update = api.uci_get_type("global_rules", "geoip_update", "1") == "1" and "checked='checked'" or "" +local geosite_update = api.uci_get_type("global_rules", "geosite_update", "1") == "1" and "checked='checked'" or "" -%>