mirror of
https://github.com/kiddin9/op-packages.git
synced 2026-11-03 07:13:56 +08:00
💋 Sync 2026-10-16 23:55:30
This commit is contained in:
1 parent
76f10c2a74
commit
1849cc6156
254 files changed
+25484
-8840
No files matched your search
@@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk
|
||||
|
||||
PKG_NAME:=luci-app-passwall
|
||||
PKG_VERSION:=26.10.16
|
||||
PKG_RELEASE:=334
|
||||
PKG_RELEASE:=335
|
||||
PKG_PO_VERSION:=$(PKG_VERSION)
|
||||
|
||||
PKG_CONFIG_DEPENDS:= \
|
||||
|
||||
@@ -710,13 +710,12 @@ if has_smartdns then
|
||||
o:value("notice", "Notice")
|
||||
o:value("info", "Info")
|
||||
o:value("debug", "Debug")
|
||||
o:depends({dns_shunt = "smartdns", log_smartdns = "1"})
|
||||
o:depends("log_smartdns", "1")
|
||||
|
||||
o = s:taboption("log", Value, "smartdns_log_size", translate("Log Size") .. " (MB)")
|
||||
o.default = "1"
|
||||
o.datatype = "and(uinteger,min(1))"
|
||||
o.rmempty = false
|
||||
o:depends({dns_shunt = "smartdns", log_smartdns = "1"})
|
||||
o:depends("log_smartdns", "1")
|
||||
|
||||
o = s:taboption("log", DummyValue, "_smartdns_log", translate("Log File"))
|
||||
o.rawhtml = true
|
||||
@@ -734,7 +733,7 @@ if has_smartdns then
|
||||
end
|
||||
return s
|
||||
end
|
||||
o:depends({dns_shunt = "smartdns", log_smartdns = "1"})
|
||||
o:depends("log_smartdns", "1")
|
||||
|
||||
if api.fs.access("/usr/lib/smartdns_ui.so") or api.fs.access("/usr/lib/smartdns/smartdns_ui.so") then
|
||||
o = s:taboption("log", Flag, "smartdns_ui", "SmartDNS " .. translate("Enable WebUI"))
|
||||
@@ -745,12 +744,10 @@ if has_smartdns then
|
||||
o = s:taboption("log", Value, "smartdns_ui_port", translate("WebUI Port"))
|
||||
o.default = "9880"
|
||||
o.datatype = "range(1,65535)"
|
||||
o.rmempty = false
|
||||
o:depends({dns_shunt = "smartdns", smartdns_ui = "1"})
|
||||
o:depends("smartdns_ui", "1")
|
||||
|
||||
o = s:taboption("log", Value, "smartdns_ui_data_dir", translate("WebUI Database Directory"))
|
||||
o.default = api.CACHE_PATH .. "/smartdns"
|
||||
o.rmempty = false
|
||||
o.validate = function(self, value, section)
|
||||
value = api.trim(value)
|
||||
if value:sub(1, 1) ~= "/" or value:find("%s") then
|
||||
@@ -758,13 +755,12 @@ if has_smartdns then
|
||||
end
|
||||
return value
|
||||
end
|
||||
o:depends({dns_shunt = "smartdns", smartdns_ui = "1"})
|
||||
o:depends("smartdns_ui", "1")
|
||||
|
||||
o = s:taboption("log", Value, "smartdns_ui_log_max_age", translate("WebUI Log Retention Days"))
|
||||
o.default = "7"
|
||||
o.datatype = "and(uinteger,min(1))"
|
||||
o.rmempty = false
|
||||
o:depends({dns_shunt = "smartdns", smartdns_ui = "1"})
|
||||
o:depends("smartdns_ui", "1")
|
||||
|
||||
o = s:taboption("log", DummyValue, "_smartdns_ui_link", "WebUI")
|
||||
o.rawhtml = true
|
||||
@@ -776,7 +772,7 @@ if has_smartdns then
|
||||
translate("Open WebUI"), port
|
||||
)
|
||||
end
|
||||
o:depends({dns_shunt = "smartdns", smartdns_ui = "1"})
|
||||
o:depends("smartdns_ui", "1")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -178,9 +178,11 @@ function get_cache_var(key)
|
||||
return val
|
||||
end
|
||||
|
||||
function get_new_port()
|
||||
local cmd_format = ". /usr/share/passwall/utils.sh ; echo -n $(get_new_port %s tcp,udp)"
|
||||
return tonumber(sys.exec(string.format(cmd_format, "auto")))
|
||||
function get_new_port(start_port, protocol)
|
||||
start_port = tonumber(start_port) or "auto"
|
||||
if protocol ~= "tcp" and protocol ~= "udp" then protocol = "tcp,udp" end
|
||||
local cmd_format = ". /usr/share/passwall/utils.sh ; echo -n $(get_new_port %s %s)"
|
||||
return tonumber(sys.exec(string.format(cmd_format, util.shellquote(tostring(start_port)), util.shellquote(protocol))))
|
||||
end
|
||||
|
||||
function exec_call(cmd)
|
||||
|
||||
@@ -17,12 +17,15 @@
|
||||
position: sticky;
|
||||
bottom: 0;
|
||||
box-shadow: 0 0 2rem 0 rgba(136, 152, 170, .3);
|
||||
color: #525f7f;
|
||||
background: #fff;
|
||||
z-index: 99;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html[data-darkmode="true"] .status-bar {
|
||||
background: #2f2f2fcc;
|
||||
}
|
||||
|
||||
.status-bar .inner {
|
||||
padding: 0.5em;
|
||||
}
|
||||
|
||||
@@ -181,6 +181,15 @@ local only_global = (DEFAULT_PROXY_MODE == "proxy" and CHN_LIST == "0" and USE_G
|
||||
if only_global == 1 then
|
||||
DEFAULT_DNS_GROUP = "proxy"
|
||||
end
|
||||
local AUTO_DIRECT_PORT = 0
|
||||
if DEFAULT_DNS_GROUP == AUTO_GROUP then
|
||||
AUTO_DIRECT_PORT = api.get_new_port(15350)
|
||||
-- 避开同一进程尚未启动的主监听和直连监听端口。
|
||||
for _ = 1, 2 do
|
||||
if not AUTO_DIRECT_PORT or (AUTO_DIRECT_PORT ~= tonumber(LISTEN_PORT) and AUTO_DIRECT_PORT ~= LOCAL_PORT) then break end
|
||||
AUTO_DIRECT_PORT = api.get_new_port(AUTO_DIRECT_PORT + 1)
|
||||
end
|
||||
end
|
||||
local force_https_soa = api.uci_get_c("@global[0]", "force_https_soa") or 0
|
||||
local force_qtype_soa = tonumber(force_https_soa) == 1 and "force-qtype-SOA 65" or "force-qtype-SOA -,65"
|
||||
local proxy_server_name = "psw-proxy-server"
|
||||
@@ -191,6 +200,7 @@ config_lines = {
|
||||
tonumber(LISTEN_PORT) ~= 0 and ("bind-tcp " .. listen_address) or "",
|
||||
LOCAL_PORT > 0 and ("bind [::]:" .. LOCAL_PORT .. "@lo -group direct -no-rules") or "",
|
||||
LOCAL_PORT > 0 and ("bind-tcp [::]:" .. LOCAL_PORT .. "@lo -group direct -no-rules") or "",
|
||||
AUTO_DIRECT_PORT > 0 and ("bind [::]:" .. AUTO_DIRECT_PORT .. "@lo -group auto-direct") or "",
|
||||
"log-level " .. LOG_LEVEL,
|
||||
"log-num " .. (LOG and "1" or "0"),
|
||||
LOG and string.format("log-file %q", FLAG_PATH .. "/smartdns.log") or "",
|
||||
@@ -236,10 +246,13 @@ if DNS_REDIRECT then
|
||||
end
|
||||
for _, server_param in ipairs(DIRECT_SERVERS) do
|
||||
table.insert(config_lines, server_param .. " -group direct -exclude-default-group")
|
||||
if DEFAULT_DNS_GROUP == AUTO_GROUP then
|
||||
-- 自动组的直连副本仅接受大陆 IP,普通直连组保持默认行为。
|
||||
table.insert(auto_config_lines, server_param .. " -group " .. AUTO_GROUP .. " -exclude-default-group -whitelist-ip")
|
||||
end
|
||||
end
|
||||
if DEFAULT_DNS_GROUP == AUTO_GROUP then
|
||||
-- 自动组先通过独立入口去除 CNAME,再按原逻辑筛选 IP。
|
||||
table.insert(auto_config_lines, "server 127.0.0.1:" .. AUTO_DIRECT_PORT .. " -group " .. AUTO_GROUP .. " -exclude-default-group -whitelist-ip")
|
||||
table.insert(auto_config_lines, "group-begin auto-direct -inherit none")
|
||||
merge_array(auto_config_lines, DIRECT_SERVERS)
|
||||
merge_array(auto_config_lines, {"force-no-CNAME yes", "group-end"})
|
||||
end
|
||||
|
||||
-- 由下方 DNS_MODE 分支调用,服务器参数来自 PassWall 的 REMOTE_DNS 或 TUN_DNS。
|
||||
|
||||
@@ -60,9 +60,26 @@ local has_singbox = api.finded_com("sing-box")
|
||||
local has_xray = api.finded_com("xray")
|
||||
local has_hysteria2 = api.finded_com("hysteria")
|
||||
local DEFAULT_ALLOWINSECURE = true
|
||||
local DEFAULT_FILTER_KEYWORD_MODE = uci_get("@global_subscribe[0]", "filter_keyword_mode") or "0"
|
||||
local DEFAULT_FILTER_KEYWORD_DISCARD_LIST = uci_get("@global_subscribe[0]", "filter_discard_list") or {}
|
||||
local DEFAULT_FILTER_KEYWORD_KEEP_LIST = uci_get("@global_subscribe[0]", "filter_keep_list") or {}
|
||||
-- 展开 DynamicList 每行中的关键字,保留原有空格并忽略空项和重复项。
|
||||
local function split_filter_keywords(list)
|
||||
local keywords, seen = {}, {}
|
||||
if type(list) == "string" then list = {list} end
|
||||
for _, row in ipairs(list or {}) do
|
||||
for keyword in row:gmatch("[^|]+") do
|
||||
if not seen[keyword] then
|
||||
seen[keyword] = true
|
||||
keywords[#keywords + 1] = keyword
|
||||
end
|
||||
end
|
||||
end
|
||||
return keywords
|
||||
end
|
||||
|
||||
local DEFAULT_FILTER_KEYWORD = {
|
||||
mode = uci_get("@global_subscribe[0]", "filter_keyword_mode") or "0",
|
||||
discard_list = split_filter_keywords(uci_get("@global_subscribe[0]", "filter_discard_list")),
|
||||
keep_list = split_filter_keywords(uci_get("@global_subscribe[0]", "filter_keep_list"))
|
||||
}
|
||||
-- 取节点使用core类型(节点订阅页面未设置时,自动取默认)
|
||||
local DEFAULT_SS_TYPE = api.get_core("ss_type", {{has_ss_rust,"shadowsocks-rust"},{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
local DEFAULT_TROJAN_TYPE = api.get_core("trojan_type", {{has_singbox,"sing-box"},{has_xray,"xray"}})
|
||||
@@ -75,71 +92,38 @@ local core_has = {
|
||||
["shadowsocks-rust"] = has_ss_rust,
|
||||
["hysteria2"] = has_hysteria2
|
||||
}
|
||||
-- 判断是否过滤节点关键字
|
||||
local function is_filter_keyword(sub_cfg, value)
|
||||
local mode = DEFAULT_FILTER_KEYWORD_MODE
|
||||
local discard_list = DEFAULT_FILTER_KEYWORD_DISCARD_LIST
|
||||
local keep_list = DEFAULT_FILTER_KEYWORD_KEEP_LIST
|
||||
if sub_cfg then
|
||||
local filter_keyword_mode = sub_cfg.filter_keyword_mode or "5" -- 5 is global
|
||||
if filter_keyword_mode == "0" then
|
||||
mode = "0"
|
||||
elseif filter_keyword_mode == "1" then
|
||||
mode = "1"
|
||||
discard_list = sub_cfg.filter_discard_list or {}
|
||||
elseif filter_keyword_mode == "2" then
|
||||
mode = "2"
|
||||
keep_list = sub_cfg.filter_keep_list or {}
|
||||
elseif filter_keyword_mode == "3" then
|
||||
mode = "3"
|
||||
keep_list = sub_cfg.filter_keep_list or {}
|
||||
discard_list = sub_cfg.filter_discard_list or {}
|
||||
elseif filter_keyword_mode == "4" then
|
||||
mode = "4"
|
||||
keep_list = sub_cfg.filter_keep_list or {}
|
||||
discard_list = sub_cfg.filter_discard_list or {}
|
||||
-- 每个订阅只准备一次过滤配置,5 / 未设置时继承全局。
|
||||
local function prepare_keyword_filter(sub_cfg)
|
||||
local mode = sub_cfg and sub_cfg.filter_keyword_mode
|
||||
if mode == "0" or mode == "1" or mode == "2" or mode == "3" or mode == "4" then
|
||||
return {
|
||||
mode = mode,
|
||||
discard_list = split_filter_keywords(sub_cfg.filter_discard_list),
|
||||
keep_list = split_filter_keywords(sub_cfg.filter_keep_list)
|
||||
}
|
||||
end
|
||||
return DEFAULT_FILTER_KEYWORD
|
||||
end
|
||||
|
||||
local function match_filter_keywords(value, keywords)
|
||||
for _, keyword in ipairs(keywords) do
|
||||
if value:find(keyword, 1, true) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
if mode == "1" then
|
||||
for k,v in ipairs(discard_list) do
|
||||
if value:find(v, 1, true) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
elseif mode == "2" then
|
||||
local result = true
|
||||
for k,v in ipairs(keep_list) do
|
||||
if value:find(v, 1, true) then
|
||||
result = false
|
||||
end
|
||||
end
|
||||
return result
|
||||
elseif mode == "3" then
|
||||
local result = false
|
||||
for k,v in ipairs(discard_list) do
|
||||
if value:find(v, 1, true) then
|
||||
result = true
|
||||
end
|
||||
end
|
||||
for k,v in ipairs(keep_list) do
|
||||
if value:find(v, 1, true) then
|
||||
result = false
|
||||
end
|
||||
end
|
||||
return result
|
||||
elseif mode == "4" then
|
||||
local result = true
|
||||
for k,v in ipairs(keep_list) do
|
||||
if value:find(v, 1, true) then
|
||||
result = false
|
||||
end
|
||||
end
|
||||
for k,v in ipairs(discard_list) do
|
||||
if value:find(v, 1, true) then
|
||||
result = true
|
||||
end
|
||||
end
|
||||
return result
|
||||
return false
|
||||
end
|
||||
|
||||
-- 节点解析出备注后,再按当前订阅的配置判断是否丢弃。
|
||||
local function is_filter_keyword(filter, value)
|
||||
if filter.mode == "1" then
|
||||
return match_filter_keywords(value, filter.discard_list)
|
||||
elseif filter.mode == "2" then
|
||||
return not match_filter_keywords(value, filter.keep_list)
|
||||
elseif filter.mode == "3" then
|
||||
return match_filter_keywords(value, filter.discard_list) and not match_filter_keywords(value, filter.keep_list)
|
||||
elseif filter.mode == "4" then
|
||||
return match_filter_keywords(value, filter.discard_list) or not match_filter_keywords(value, filter.keep_list)
|
||||
end
|
||||
return false
|
||||
end
|
||||
@@ -2146,6 +2130,7 @@ local function parse_link(raw, add_mode, group, sub_cfg)
|
||||
if sub_cfg then
|
||||
cfgid = sub_cfg[".name"]
|
||||
end
|
||||
local keyword_filter = add_mode == "2" and prepare_keyword_filter(sub_cfg)
|
||||
local nodes, szType
|
||||
local node_list = {}
|
||||
-- SSD 似乎是这种格式 ssd:// 开头的
|
||||
@@ -2202,7 +2187,7 @@ local function parse_link(raw, add_mode, group, sub_cfg)
|
||||
log('丢弃节点:' .. result.remarks .. " ,原因:" .. result.error_msg)
|
||||
elseif not result.type then
|
||||
log('丢弃节点:' .. result.remarks .. " ,找不到可使用二进制。")
|
||||
elseif (add_mode == "2" and is_filter_keyword(sub_cfg, result.remarks)) or not result.address or result.remarks == "NULL" or result.address == "127.0.0.1" or
|
||||
elseif (add_mode == "2" and is_filter_keyword(keyword_filter, result.remarks)) or not result.address or result.remarks == "NULL" or result.address == "127.0.0.1" or
|
||||
(not datatypes.hostname(result.address) and not (api.is_ip(result.address))) then
|
||||
log('丢弃过滤节点:' .. result.type .. ' 节点,' .. result.remarks)
|
||||
else
|
||||
|
||||
Reference in new issue
Block a user