diff --git a/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js b/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js index d958ab6a..052bcaea 100644 --- a/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js +++ b/luci-app-dockerman/htdocs/luci-static/resources/view/dockerman/container_new.js @@ -251,6 +251,7 @@ return dm2.dv.extend({ let dnet = this.section.getOption('network').getUIElement(section_id).getValue(); const disallowed = builtInNetworks.has(dnet); if (disallowed) return _('Only for user-defined networks'); + return true; }; o = s.option(form.Value, 'ipv4', _('IPv4 Address')); diff --git a/luci-app-momo/Makefile b/luci-app-momo/Makefile index 620a5453..c063ebef 100644 --- a/luci-app-momo/Makefile +++ b/luci-app-momo/Makefile @@ -1,7 +1,7 @@ include $(TOPDIR)/rules.mk PKG_VERSION:=1.1.1 -PKG_RELEASE:=2 +PKG_RELEASE:=3 LUCI_TITLE:=LuCI Support for momo LUCI_DEPENDS:=+luci-base +momo diff --git a/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js b/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js index 7eafe9e0..22641512 100644 --- a/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js +++ b/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js @@ -24,6 +24,34 @@ return view.extend({ m = new form.Map('momo'); + s = m.section(form.NamedSection, 'log', 'log', _('Log Cleanup')); + + o = s.option(form.Flag, 'log_cleanup_enabled', _('Scheduled Log Cleanup')); + o.rmempty = false; + + o = s.option(form.Value, 'log_cleanup_cron_expression', _('Log Cleanup Cron Expression')); + o.retain = true; + o.rmempty = false; + o.placeholder = '0 4 * * *'; + o.depends('log_cleanup_enabled', '1'); + o.description = _('Run unconditional log cleanup at the configured cron schedule.'); + + o = s.option(form.Flag, 'log_cleanup_size_enabled', _('Size-based Log Cleanup')); + o.rmempty = false; + + o = s.option(form.Value, 'log_cleanup_size_check_cron_expression', _('Log Size Check Cron Expression')); + o.retain = true; + o.rmempty = false; + o.placeholder = '*/30 * * * *'; + o.depends('log_cleanup_size_enabled', '1'); + o.description = _('Check log size at the configured cron schedule before cleaning up.'); + + o = s.option(form.Value, 'log_cleanup_size_mb', _('Log Cleanup Size Threshold (MB)')); + o.datatype = 'uinteger'; + o.placeholder = '50'; + o.depends('log_cleanup_size_enabled', '1'); + o.description = _('Clear app, core and debug logs when their total size reaches this threshold.'); + s = m.section(form.NamedSection, 'placeholder', 'placeholder', _('Log')); s.tab('app_log', _('App Log')); @@ -119,8 +147,5 @@ return view.extend({ }; return m.render(); - }, - handleSaveApply: null, - handleSave: null, - handleReset: null -}); \ No newline at end of file + } +}); diff --git a/luci-app-momo/po/templates/momo.pot b/luci-app-momo/po/templates/momo.pot index d2eafbb4..3b4e7bde 100644 --- a/luci-app-momo/po/templates/momo.pot +++ b/luci-app-momo/po/templates/momo.pot @@ -425,3 +425,39 @@ msgstr "" #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:128 msgid "procd Config" msgstr "" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:47 +msgid "Check log size at the configured cron schedule before cleaning up." +msgstr "" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:53 +msgid "Clear app, core and debug logs when their total size reaches this threshold." +msgstr "" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:27 +msgid "Log Cleanup" +msgstr "" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:32 +msgid "Log Cleanup Cron Expression" +msgstr "" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:49 +msgid "Log Cleanup Size Threshold (MB)" +msgstr "" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:42 +msgid "Log Size Check Cron Expression" +msgstr "" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:37 +msgid "Run unconditional log cleanup at the configured cron schedule." +msgstr "" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:29 +msgid "Scheduled Log Cleanup" +msgstr "" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:39 +msgid "Size-based Log Cleanup" +msgstr "" diff --git a/luci-app-momo/po/zh_Hans/momo.po b/luci-app-momo/po/zh_Hans/momo.po index 43ded6ef..6ee9ae13 100644 --- a/luci-app-momo/po/zh_Hans/momo.po +++ b/luci-app-momo/po/zh_Hans/momo.po @@ -432,3 +432,39 @@ msgstr "用户代理(UA)" #: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/app.js:128 msgid "procd Config" msgstr "procd 配置" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:47 +msgid "Check log size at the configured cron schedule before cleaning up." +msgstr "按设定的 Cron 周期检查日志大小,满足条件后再清理。" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:53 +msgid "Clear app, core and debug logs when their total size reaches this threshold." +msgstr "当插件日志、核心日志和调试日志总大小达到该阈值时自动清理。" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:27 +msgid "Log Cleanup" +msgstr "日志清理" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:32 +msgid "Log Cleanup Cron Expression" +msgstr "日志清理 Cron 表达式" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:49 +msgid "Log Cleanup Size Threshold (MB)" +msgstr "日志清理大小阈值(MB)" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:42 +msgid "Log Size Check Cron Expression" +msgstr "日志大小检查 Cron 表达式" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:37 +msgid "Run unconditional log cleanup at the configured cron schedule." +msgstr "按设定的 Cron 时间无条件执行日志清理。" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:29 +msgid "Scheduled Log Cleanup" +msgstr "定时日志清理" + +#: applications/luci-app-momo/htdocs/luci-static/resources/view/momo/log.js:39 +msgid "Size-based Log Cleanup" +msgstr "按大小触发日志清理" diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/hysteria2.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/hysteria2.lua index e06eb72d..0aa837c1 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/hysteria2.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/hysteria2.lua @@ -32,9 +32,10 @@ o = s:option(Value, _n("hop"), translate("Port hopping range")) o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o.rewrite_option = o.option -o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") -o.placeholder = "30s" -o.default = "30s" +o = s:option(Value, _n("hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5.")) +o.datatype = "or(uinteger,portrange)" +o.placeholder = "30" +o.default = "30" o.rewrite_option = o.option o = s:option(Value, _n("obfs"), translate("Obfs Password")) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua index 0701c514..891ed102 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/ray.lua @@ -305,9 +305,10 @@ o = s:option(Value, _n("hysteria2_hop"), translate("Port hopping range")) o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria2" }) -o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") -o.placeholder = "30s" -o.default = "30s" +o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5.")) +o.datatype = "or(uinteger,portrange)" +o.placeholder = "30" +o.default = "30" o:depends({ [_n("protocol")] = "hysteria2" }) o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua index 58a6a9ab..95c0a2a0 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/type/sing-box.lua @@ -278,9 +278,10 @@ if singbox_tags:find("with_quic") then o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria" }) - o = s:option(Value, _n("hysteria_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") - o.placeholder = "30s" - o.default = "30s" + o = s:option(Value, _n("hysteria_hop_interval"), translate("Hop Interval(second)"), translate("Example:") .. "30 (≥5)") + o.datatype = "uinteger" + o.placeholder = "30" + o.default = "30" o:depends({ [_n("protocol")] = "hysteria" }) o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password")) @@ -362,9 +363,10 @@ if singbox_tags:find("with_quic") then o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria2" }) - o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") - o.placeholder = "30s" - o.default = "30s" + o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(Second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5.")) + o.datatype = "or(uinteger,portrange)" + o.placeholder = "30" + o.default = "30" o:depends({ [_n("protocol")] = "hysteria2" }) o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) diff --git a/luci-app-passwall/luasrc/passwall/util_hysteria2.lua b/luci-app-passwall/luasrc/passwall/util_hysteria2.lua index 9d2db50a..817ae978 100644 --- a/luci-app-passwall/luasrc/passwall/util_hysteria2.lua +++ b/luci-app-passwall/luasrc/passwall/util_hysteria2.lua @@ -64,16 +64,27 @@ function gen_config(var) server = server, transport = { type = "udp", - udp = { - hopInterval = (function() - local HopIntervalStr = tostring(node.hysteria2_hop_interval or "30s") - local HopInterval = tonumber(HopIntervalStr:match("^%d+")) - if HopInterval and HopInterval >= 5 then - return tostring(HopInterval) .. "s" - end - return "30s" - end)(), - } + udp = node.hysteria2_hop and (function() + local udp = {} + local t = node.hysteria2_hop_interval + if not t then return nil end + if t:find("-", 1, true) then + local min, max = t:match("^(%d+)%-(%d+)$") + min = tonumber(min) + max = tonumber(max) + if min and max then + min = (min >= 5) and min or 5 + max = (max >= min) and max or min + udp.minHopInterval = min .. "s" + udp.maxHopInterval = max .. "s" + return udp + end + end + t = tonumber((t or "30"):match("^%d+")) + t = (t and t >= 5) and t or 30 + udp.hopInterval = t .. "s" + return udp + end)() or nil }, obfs = (node.hysteria2_obfs) and { type = "salamander", diff --git a/luci-app-passwall/luasrc/passwall/util_sing-box.lua b/luci-app-passwall/luasrc/passwall/util_sing-box.lua index 71313fed..9bb79dee 100644 --- a/luci-app-passwall/luasrc/passwall/util_sing-box.lua +++ b/luci-app-passwall/luasrc/passwall/util_sing-box.lua @@ -421,7 +421,7 @@ function gen_outbound(flag, node, tag, proxy_table) server_ports = next(server_ports) and server_ports or nil, hop_interval = (function() if not next(server_ports) then return nil end - local v = tonumber((node.hysteria_hop_interval or "30s"):match("^%d+")) + local v = tonumber((node.hysteria_hop_interval or "30"):match("^%d+")) return (v and v >= 5) and (v .. "s") or "30s" end)(), up_mbps = tonumber(node.hysteria_up_mbps), @@ -474,13 +474,30 @@ function gen_outbound(flag, node, tag, proxy_table) end end end + local interval, interval_max + if next(server_ports) then + interval = "30s" + local t = node.hysteria2_hop_interval or "30s" + if t:find("-", 1, true) then + local min, max = t:match("^(%d+)%-(%d+)$") + min = tonumber(min) + max = tonumber(max) + if min and max then + min = (min >= 5) and min or 5 + max = (max >= min) and max or min + interval = min .. "s" + interval_max = max .. "s" + end + else + t = tonumber(t:match("^%d+")) + t = (t and t >= 5) and t or 30 + interval = t .. "s" + end + end protocol_table = { server_ports = next(server_ports) and server_ports or nil, - hop_interval = (function() - if not next(server_ports) then return nil end - local v = tonumber((node.hysteria2_hop_interval or "30s"):match("^%d+")) - return (v and v >= 5) and (v .. "s") or "30s" - end)(), + hop_interval = interval, + hop_interval_max = interval_max, up_mbps = (node.hysteria2_up_mbps and tonumber(node.hysteria2_up_mbps)) and tonumber(node.hysteria2_up_mbps) or nil, down_mbps = (node.hysteria2_down_mbps and tonumber(node.hysteria2_down_mbps)) and tonumber(node.hysteria2_down_mbps) or nil, obfs = node.hysteria2_obfs_type and { diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index 87d0690a..2ad66e8f 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -284,7 +284,19 @@ function gen_outbound(flag, node, tag, proxy_table) udpHop = (node.hysteria2_hop) and { ports = string.gsub(node.hysteria2_hop, ":", "-"), interval = (function(v) - v = tonumber((v or "30s"):match("^%d+")) + if not v then return 30 end + if v:find("-", 1, true) then + local min, max = v:match("^(%d+)%-(%d+)$") + min = tonumber(min) + max = tonumber(max) + if min and max then + min = (min >= 5) and min or 5 + max = (max >= min) and max or min + return min .. "-" .. max + end + return 30 + end + v = tonumber((v or "30"):match("^%d+")) return (v and v >= 5) and v or 30 end)(node.hysteria2_hop_interval) } or nil, 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 f04021a9..2feb6729 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 @@ -962,7 +962,11 @@ table td, .table .td { } else { innerHTML = innerHTML.split("{{tcping}}").join('---'); } - innerHTML = innerHTML.split("{{url_test}}").join('<%:Test%>'); + if (o["protocol"] && o["protocol"] !== '_shunt') { + innerHTML = innerHTML.split("{{url_test}}").join('<%:Test%>'); + } else { + innerHTML = innerHTML.split("{{url_test}}").join('---'); + } innerHTML = innerHTML.split("{{id}}").join(o[".name"]); innerHTML = innerHTML.split("{{group}}").join(o["group"] || ""); let node_remarks = get_remarks_name(o); diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po index 720bf3e9..93a40372 100644 --- a/luci-app-passwall/po/zh-cn/passwall.po +++ b/luci-app-passwall/po/zh-cn/passwall.po @@ -1807,14 +1807,14 @@ msgstr "缓冲区大小" msgid "Buffer size for every connection (kB)" msgstr "每一个连接的缓冲区大小(kB)" -msgid "Handshake Timeout" -msgstr "握手超时 " - msgid "Idle Timeout" -msgstr "空闲超时 " +msgstr "空闲超时" -msgid "Hop Interval" -msgstr "端口跳跃时间 " +msgid "Hop Interval(second)" +msgstr "端口跳跃间隔(秒)" + +msgid "Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5." +msgstr "支持固定值或随机范围(如 30 或 5-30),最小 5 秒。" msgid "HeartbeatPeriod(second)" msgstr "心跳周期(单位:秒)" diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua index 7a0e38f2..f50db48a 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/hysteria2.lua @@ -29,9 +29,10 @@ o = s:option(Value, _n("hop"), translate("Port hopping range")) o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o.rewrite_option = o.option -o = s:option(Value, _n("hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") -o.placeholder = "30s" -o.default = "30s" +o = s:option(Value, _n("hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5.")) +o.datatype = "or(uinteger,portrange)" +o.placeholder = "30" +o.default = "30" o.rewrite_option = o.option o = s:option(Value, _n("obfs"), translate("Obfs Password")) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua index 804b270e..ef70a93c 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ray.lua @@ -295,6 +295,7 @@ o = s:option(ListValue, _n("flow"), translate("flow")) o.default = "" o:value("", translate("Disable")) o:value("xtls-rprx-vision") +o:value("xtls-rprx-vision-udp443") o:depends({ [_n("protocol")] = "vless" }) ---- [[hysteria2]] @@ -302,9 +303,10 @@ o = s:option(Value, _n("hysteria2_hop"), translate("Port hopping range")) o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria2" }) -o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") -o.placeholder = "30s" -o.default = "30s" +o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5.")) +o.datatype = "or(uinteger,portrange)" +o.placeholder = "30" +o.default = "30" o:depends({ [_n("protocol")] = "hysteria2" }) o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua index 4524e81a..a69ac4fd 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/sing-box.lua @@ -315,9 +315,10 @@ if singbox_tags:find("with_quic") then o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria" }) - o = s:option(Value, _n("hysteria_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") - o.placeholder = "30s" - o.default = "30s" + o = s:option(Value, _n("hysteria_hop_interval"), translate("Hop Interval(second)"), translate("Example:") .. "30 (≥5)") + o.datatype = "uinteger" + o.placeholder = "30" + o.default = "30" o:depends({ [_n("protocol")] = "hysteria" }) o = s:option(Value, _n("hysteria_obfs"), translate("Obfs Password")) @@ -399,9 +400,10 @@ if singbox_tags:find("with_quic") then o.description = translate("Format as 1000:2000 or 1000-2000 Multiple groups are separated by commas (,).") o:depends({ [_n("protocol")] = "hysteria2" }) - o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval"), translate("Example:") .. "30s (≥5s)") - o.placeholder = "30s" - o.default = "30s" + o = s:option(Value, _n("hysteria2_hop_interval"), translate("Hop Interval(Second)"), translate("Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5.")) + o.datatype = "or(uinteger,portrange)" + o.placeholder = "30" + o.default = "30" o:depends({ [_n("protocol")] = "hysteria2" }) o = s:option(Value, _n("hysteria2_up_mbps"), translate("Max upload Mbps")) diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua index 169892c9..3a3e43ef 100644 --- a/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/luci-app-passwall2/luasrc/passwall2/api.lua @@ -1561,3 +1561,34 @@ function cleanEmptyTables(t) end return next(t) and t or nil end + +function get_dnsmasq_server_domain() + local dnsmasq_server = uci:get("dhcp", "@dnsmasq[0]", "server") + local dnsmasq_server_t = {} + if dnsmasq_server and #dnsmasq_server > 0 then + for k, v in ipairs(dnsmasq_server) do + if v:find("/") then + local split1 = split(v, "/") + if #split1 > 2 then + local domain = split1[2] + local upstream_dns = split1[#split1] + local upstream_dns_server + local upstream_dns_port = "53" + local dns_split = split(upstream_dns, "#") + if #dns_split > 1 then + upstream_dns_server = dns_split[1] + upstream_dns_port = dns_split[#dns_split] + else + upstream_dns_server = upstream_dns + end + dnsmasq_server_t[domain] = { + dnsmasq_dns = upstream_dns, + server = upstream_dns_server, + port = tonumber(upstream_dns_port) + } + end + end + end + end + return dnsmasq_server_t +end \ No newline at end of file diff --git a/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua b/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua index 51d310d6..a06928a4 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_hysteria2.lua @@ -61,16 +61,27 @@ function gen_config(var) server = server, transport = { type = "udp", - udp = { - hopInterval = (function() - local HopIntervalStr = tostring(node.hysteria2_hop_interval or "30s") - local HopInterval = tonumber(HopIntervalStr:match("^%d+")) - if HopInterval and HopInterval >= 5 then - return tostring(HopInterval) .. "s" - end - return "30s" - end)(), - } + udp = node.hysteria2_hop and (function() + local udp = {} + local t = node.hysteria2_hop_interval + if not t then return nil end + if t:find("-", 1, true) then + local min, max = t:match("^(%d+)%-(%d+)$") + min = tonumber(min) + max = tonumber(max) + if min and max then + min = (min >= 5) and min or 5 + max = (max >= min) and max or min + udp.minHopInterval = min .. "s" + udp.maxHopInterval = max .. "s" + return udp + end + end + t = tonumber((t or "30"):match("^%d+")) + t = (t and t >= 5) and t or 30 + udp.hopInterval = t .. "s" + return udp + end)() or nil }, obfs = (node.hysteria2_obfs) and { type = "salamander", diff --git a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua index fa250870..a76de67a 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_sing-box.lua @@ -153,7 +153,7 @@ function gen_outbound(flag, node, tag, proxy_table) server = node.address, server_port = tonumber(node.port), domain_resolver = { - server = "direct", + server = "local", strategy = node.domain_strategy }, detour = node.detour, @@ -436,7 +436,7 @@ function gen_outbound(flag, node, tag, proxy_table) server_ports = next(server_ports) and server_ports or nil, hop_interval = (function() if not next(server_ports) then return nil end - local v = tonumber((node.hysteria_hop_interval or "30s"):match("^%d+")) + local v = tonumber((node.hysteria_hop_interval or "30"):match("^%d+")) return (v and v >= 5) and (v .. "s") or "30s" end)(), up_mbps = tonumber(node.hysteria_up_mbps), @@ -489,13 +489,30 @@ function gen_outbound(flag, node, tag, proxy_table) end end end + local interval, interval_max + if next(server_ports) then + interval = "30s" + local t = node.hysteria2_hop_interval or "30s" + if t:find("-", 1, true) then + local min, max = t:match("^(%d+)%-(%d+)$") + min = tonumber(min) + max = tonumber(max) + if min and max then + min = (min >= 5) and min or 5 + max = (max >= min) and max or min + interval = min .. "s" + interval_max = max .. "s" + end + else + t = tonumber(t:match("^%d+")) + t = (t and t >= 5) and t or 30 + interval = t .. "s" + end + end protocol_table = { server_ports = next(server_ports) and server_ports or nil, - hop_interval = (function() - if not next(server_ports) then return nil end - local v = tonumber((node.hysteria2_hop_interval or "30s"):match("^%d+")) - return (v and v >= 5) and (v .. "s") or "30s" - end)(), + hop_interval = interval, + hop_interval_max = interval_max, up_mbps = (node.hysteria2_up_mbps and tonumber(node.hysteria2_up_mbps)) and tonumber(node.hysteria2_up_mbps) or nil, down_mbps = (node.hysteria2_down_mbps and tonumber(node.hysteria2_down_mbps)) and tonumber(node.hysteria2_down_mbps) or nil, obfs = node.hysteria2_obfs_type and { @@ -901,7 +918,7 @@ function gen_config_server(node) outbound = require("luci.passwall2.util_sing-box").gen_outbound(nil, outbound_node_t, "outbound") end if outbound then - route.final = "outbound" + route.final = outbound.tag table.insert(outbounds, 1, outbound) end end @@ -913,6 +930,14 @@ function gen_config_server(node) timestamp = true, --output = logfile, }, + dns = { + servers = { + { + type = "local", + tag = "local" + } + } + }, inbounds = { inbound }, outbounds = outbounds, route = route @@ -973,7 +998,7 @@ function gen_config(var) local no_run = var["no_run"] local dns_domain_rules = {} - local dns = nil + local dns = {} local inbounds = {} local outbounds = {} local rule_set_table = {} @@ -1661,16 +1686,21 @@ function gen_config(var) route.final = COMMON.default_outbound_tag end - if dns_listen_port then - dns = { - servers = {}, - rules = {}, - disable_cache = (dns_cache and dns_cache == "0") and true or false, - disable_expire = false, -- Disable DNS cache expiration. - independent_cache = false, -- Make each DNS server's cache independent for specific purposes. If enabled, it will slightly reduce performance. - reverse_mapping = true, -- After responding to a DNS query, a reverse mapping of the IP address is stored to provide the domain name for routing purposes. - } + dns = { + servers = {}, + rules = {}, + disable_cache = (dns_cache and dns_cache == "0") and true or false, + disable_expire = false, -- Disable DNS cache expiration. + independent_cache = false, -- Make each DNS server's cache independent for specific purposes. If enabled, it will slightly reduce performance. + reverse_mapping = true, -- After responding to a DNS query, a reverse mapping of the IP address is stored to provide the domain name for routing purposes. + } + table.insert(dns.servers, { + type = "local", + tag = "local" + }) + + if dns_listen_port then local dns_host = "" if flag == "global" then dns_host = uci:get(appname, "@global[0]", "dns_hosts") or "" @@ -1802,8 +1832,8 @@ function gen_config(var) end) if #domain > 0 then table.insert(dns_domain_rules, 1, { - outboundTag = "direct", - domain = domain + domain = domain, + outboundTag = "direct" }) end @@ -1825,6 +1855,42 @@ function gen_config(var) }) end + local dnsmasq_server_domain = api.get_dnsmasq_server_domain() + if next(dnsmasq_server_domain) then + local new_dns_servers = {} + for domain, v in pairs(dnsmasq_server_domain) do + if not new_dns_servers[v.dnsmasq_dns] then + new_dns_servers[v.dnsmasq_dns] = { + server = { + tag = v.dnsmasq_dns, + type = "udp", + server = v.server, + server_port = v.port, + detour = "direct", + }, + rule = { + action = "route", + domain_suffix = {}, + server = v.dnsmasq_dns, + strategy = direct_strategy, + }, + } + end + table.insert(new_dns_servers[v.dnsmasq_dns].rule.domain_suffix, domain) + end + for k, v in pairs(new_dns_servers) do + table.insert(dns.servers, v.server) + table.insert(dns.rules, 1, v.rule) + table.insert(route.rules, 1, { + action = "route", + network = v.server.type, + ip_cidr = v.server.server, + port = v.server.server_port, + outbound = "direct", + }) + end + end + local default_dns_flag = "remote" if node_id and redir_port then local node = get_node_by_id(node_id) @@ -1843,7 +1909,7 @@ function gen_config(var) if value.outboundTag and (value.domain or value.domain_suffix or value.domain_keyword or value.domain_regex or value.rule_set) then local dns_rule = { action = "route", - server = value.outboundTag, + server = value.server or value.outboundTag, domain = (value.domain and #value.domain > 0) and value.domain or nil, domain_suffix = (value.domain_suffix and #value.domain_suffix > 0) and value.domain_suffix or nil, domain_keyword = (value.domain_keyword and #value.domain_keyword > 0) and value.domain_keyword or nil, @@ -1917,7 +1983,7 @@ function gen_config(var) listen_port = tonumber(dns_listen_port), } table.insert(inbounds, dns_in_inbound) - table.insert(route.rules, { + table.insert(route.rules, 1, { action = "sniff", inbound = dns_in_inbound.tag }) @@ -1961,15 +2027,6 @@ function gen_config(var) end end - if not dns then - dns = { - servers = {{ - type = "local", - tag = "direct" - }} - } - end - if next(ech_domain) ~= nil then table.insert(dns.servers, { tag = "ech-dns", @@ -2018,7 +2075,7 @@ function gen_config(var) tag = "direct", routing_mark = 255, domain_resolver = { - server = "direct", + server = "local", strategy = "prefer_ipv6" } }) @@ -2026,6 +2083,9 @@ function gen_config(var) if not value["_flag_proxy_tag"] and not value.detour and value["_id"] and value.server and value.server_port and not no_run then sys.call(string.format("echo '%s' >> %s", value["_id"], api.TMP_PATH .. "/direct_node_list")) end + if value.detour then + value.domain_resolver = nil + end for k, v in pairs(config.outbounds[index]) do if k:find("_") == 1 then config.outbounds[index][k] = nil @@ -2039,7 +2099,7 @@ function gen_config(var) if value.type == "wireguard" then -- https://sing-box.sagernet.org/migration/#migrate-wireguard-outbound-to-endpoint local endpoint = { - type = "wireguard", + type = value.type, tag = value.tag, system = value.system_interface, name = value.interface_name, @@ -2056,10 +2116,7 @@ function gen_config(var) reserved = value.reserved } }, - domain_resolver = { - server = "direct", - strategy = value.domain_strategy - }, + domain_resolver = value.domain_resolver, detour = value.detour } endpoints[#endpoints + 1] = endpoint diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua index 6093ad4f..81304d57 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -280,7 +280,19 @@ function gen_outbound(flag, node, tag, proxy_table) udpHop = (node.hysteria2_hop) and { ports = string.gsub(node.hysteria2_hop, ":", "-"), interval = (function(v) - v = tonumber((v or "30s"):match("^%d+")) + if not v then return 30 end + if v:find("-", 1, true) then + local min, max = v:match("^(%d+)%-(%d+)$") + min = tonumber(min) + max = tonumber(max) + if min and max then + min = (min >= 5) and min or 5 + max = (max >= min) and max or min + return min .. "-" .. max + end + return 30 + end + v = tonumber((v or "30"):match("^%d+")) return (v and v >= 5) and v or 30 end)(node.hysteria2_hop_interval) } or nil, @@ -694,6 +706,14 @@ function gen_config_server(node) end end + for index, value in ipairs(config.outbounds) do + for k, v in pairs(config.outbounds[index]) do + if k:find("_") == 1 then + config.outbounds[index][k] = nil + end + end + end + return config end @@ -734,7 +754,7 @@ function gen_config(var) local no_run = var["no_run"] local dns_domain_rules = {} - local dns = nil + local dns = {} local fakedns = nil local inbounds = {} local outbounds = {} @@ -1063,17 +1083,17 @@ function gen_config(var) local to_node = get_node_by_id(node.to_node) if to_node then -- Landing Node not support use special node. - if to_node.protocol:find("^_") then + if to_node.protocol and to_node.protocol:find("^_") then to_node = nil end end if to_node then local to_outbound if to_node.type ~= "Xray" then - local tag = to_node[".name"] + local in_tag = "inbound_" .. to_node[".name"] .. "_" .. tostring(outbound.tag) local new_port = api.get_new_port() table.insert(inbounds, { - tag = tag, + tag = in_tag, listen = "127.0.0.1", port = new_port, protocol = "dokodemo-door", @@ -1085,11 +1105,11 @@ function gen_config(var) to_node.address = "127.0.0.1" to_node.port = new_port table.insert(rules, 1, { - inboundTag = {tag}, + inboundTag = {in_tag}, outboundTag = outbound.tag }) - to_outbound = gen_outbound(node[".name"], to_node, tag, { - tag = tag, + to_outbound = gen_outbound(node[".name"], to_node, to_node[".name"], { + tag = to_node[".name"], run_socks_instance = not no_run }) else @@ -1365,13 +1385,31 @@ function gen_config(var) } end end - + + dns = { + tag = "dns-global", + hosts = {}, + disableCache = (dns_cache and dns_cache == "0") and true or false, + disableFallback = true, + disableFallbackIfMatch = true, + servers = {}, + queryStrategy = "UseIP" + } + + local dns_servers = {} + + table.insert(dns_servers, { + server = { + tag = "local", + address = "localhost" + } + }) + if dns_listen_port then local direct_dns_tag = "dns-in-direct" local remote_dns_tag = "dns-in-remote" local remote_fakedns_tag = "dns-in-remote-fakedns" local default_dns_tag = "dns-in-default" - local dns_servers = {} local _remote_dns_proto = "tcp" @@ -1382,16 +1420,6 @@ function gen_config(var) } end - dns = { - tag = "dns-global", - hosts = {}, - disableCache = (dns_cache and dns_cache == "0") and true or false, - disableFallback = true, - disableFallbackIfMatch = true, - servers = {}, - queryStrategy = "UseIP" - } - local dns_host = "" if flag == "global" then dns_host = uci:get(appname, "@global[0]", "dns_hosts") or "" @@ -1510,6 +1538,39 @@ function gen_config(var) }) end end + + local dnsmasq_server_domain = api.get_dnsmasq_server_domain() + if next(dnsmasq_server_domain) then + local new_dns_servers = {} + for domain, v in pairs(dnsmasq_server_domain) do + if not new_dns_servers[v.dnsmasq_dns] then + new_dns_servers[v.dnsmasq_dns] = { + server = { + tag = v.dnsmasq_dns, + address = v.server, + port = v.port, + queryStrategy = (direct_dns_query_strategy and direct_dns_query_strategy ~= "") and direct_dns_query_strategy or "UseIP" + }, + domain = {} + } + end + table.insert(new_dns_servers[v.dnsmasq_dns].domain, domain) + end + for k, v in pairs(new_dns_servers) do + table.insert(dns_domain_rules, 1, { + shunt_rule_name = k, + outboundTag = "direct", + dns_server = v.server, + domain = v.domain + }) + table.insert(routing.rules, 1, { + network = "udp", + ip = v.server.address, + port = v.server.port, + outboundTag = "direct" + }) + end + end if dns_listen_port then table.insert(inbounds, { @@ -1590,7 +1651,9 @@ function gen_config(var) if value.domain and value.outboundTag then local dns_server = nil local dns_outboundTag = value.outboundTag - if value.outboundTag == "direct" then + if value.dns_server then + dns_server = api.clone(value.dns_server) + elseif value.outboundTag == "direct" then dns_server = api.clone(_direct_dns) else if value.fakedns then @@ -1657,15 +1720,6 @@ function gen_config(var) table.insert(routing.rules, default_rule) 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 - local content = flag .. node_id .. jsonc.stringify(routing.rules) if api.cacheFileCompareToLogic(CACHE_TEXT_FILE, content) == false then --clear ipset/nftset @@ -1701,6 +1755,10 @@ function gen_config(var) end end + if not next(dns.hosts) then + dns.hosts = nil + end + if redir_port then local inbound = { port = tonumber(redir_port), diff --git a/luci-app-passwall2/luasrc/view/passwall2/node_config/link_share_man.htm b/luci-app-passwall2/luasrc/view/passwall2/node_config/link_share_man.htm index 53ff4c46..d1941043 100644 --- a/luci-app-passwall2/luasrc/view/passwall2/node_config/link_share_man.htm +++ b/luci-app-passwall2/luasrc/view/passwall2/node_config/link_share_man.htm @@ -1455,7 +1455,7 @@ local current_node = map:get(section) opt.set(dom_prefix + 'port', m.port || "443"); opt.set(dom_prefix + 'encryption', queryParam.encryption || "none"); - opt.set(dom_prefix + 'flow', (queryParam.flow || '').replace('-udp443', '')); + opt.set(dom_prefix + 'flow', queryParam.flow || ''); if (queryParam.security) { if (queryParam.security == "tls") { opt.set(dom_prefix + 'tls', true); diff --git a/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm b/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm index 532e0b10..d067da1e 100644 --- a/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm +++ b/luci-app-passwall2/luasrc/view/passwall2/node_list/node_list.htm @@ -963,7 +963,11 @@ table td, .table .td { } else { innerHTML = innerHTML.split("{{tcping}}").join('---'); } - innerHTML = innerHTML.split("{{url_test}}").join('<%:Test%>'); + if (o["address"] && o["port"]) { + innerHTML = innerHTML.split("{{url_test}}").join('<%:Test%>'); + } else { + innerHTML = innerHTML.split("{{url_test}}").join('---'); + } innerHTML = innerHTML.split("{{id}}").join(o[".name"]); innerHTML = innerHTML.split("{{group}}").join(o["group"] || ""); let node_remarks = get_remarks_name(o); diff --git a/luci-app-passwall2/po/fa/passwall2.po b/luci-app-passwall2/po/fa/passwall2.po index 177d1409..2d7dab7b 100644 --- a/luci-app-passwall2/po/fa/passwall2.po +++ b/luci-app-passwall2/po/fa/passwall2.po @@ -1638,14 +1638,14 @@ msgstr "اندازه بافر" msgid "Buffer size for every connection (kB)" msgstr "اندازه بافر برای هر اتصال (کیلوبایت)" -msgid "Handshake Timeout" -msgstr "مهلت زمانی دست تکان دادن" - msgid "Idle Timeout" msgstr "مهلت زمانی بیکاری" -msgid "Hop Interval" -msgstr "بازه پرش (Hop)" +msgid "Hop Interval(second)" +msgstr "فاصله پرش (ثانیه)" + +msgid "Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5." +msgstr "از یک مقدار ثابت یا یک محدوده تصادفی (مثلاً 30، 5-30)، حداقل 5، پشتیبانی می‌کند." msgid "HeartbeatPeriod(second)" msgstr "دوره ضربان قلب (ثانیه)" diff --git a/luci-app-passwall2/po/ru/passwall2.po b/luci-app-passwall2/po/ru/passwall2.po index c413809f..fd19b737 100644 --- a/luci-app-passwall2/po/ru/passwall2.po +++ b/luci-app-passwall2/po/ru/passwall2.po @@ -1639,14 +1639,14 @@ msgstr "Размер буфера" msgid "Buffer size for every connection (kB)" msgstr "Размер буфера для каждого соединения (КБ)" -msgid "Handshake Timeout" -msgstr "Тайм-аут рукопожатия" - msgid "Idle Timeout" msgstr "Тайм-аут простоя" -msgid "Hop Interval" -msgstr "Интервал смены порта" +msgid "Hop Interval(second)" +msgstr "Интервал прыжков (секунды)" + +msgid "Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5." +msgstr "Поддерживается фиксированное значение или случайный диапазон (например, 30, 5-30), минимум 5." msgid "HeartbeatPeriod(second)" msgstr "Период heartbeat-пакетов (сек)" diff --git a/luci-app-passwall2/po/zh-cn/passwall2.po b/luci-app-passwall2/po/zh-cn/passwall2.po index 75397943..c9d5ec1d 100644 --- a/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/luci-app-passwall2/po/zh-cn/passwall2.po @@ -1630,14 +1630,14 @@ msgstr "缓冲区大小" msgid "Buffer size for every connection (kB)" msgstr "每一个连接的缓冲区大小(kB)" -msgid "Handshake Timeout" -msgstr "握手超时 " - msgid "Idle Timeout" -msgstr "空闲超时 " +msgstr "空闲超时" -msgid "Hop Interval" -msgstr "端口跳跃时间 " +msgid "Hop Interval(second)" +msgstr "端口跳跃间隔(秒)" + +msgid "Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5." +msgstr "支持固定值或随机范围(如 30 或 5-30),最小 5 秒。" msgid "HeartbeatPeriod(second)" msgstr "心跳周期(单位:秒)" diff --git a/luci-app-passwall2/po/zh-tw/passwall2.po b/luci-app-passwall2/po/zh-tw/passwall2.po index a5bbe351..9ffae2b5 100644 --- a/luci-app-passwall2/po/zh-tw/passwall2.po +++ b/luci-app-passwall2/po/zh-tw/passwall2.po @@ -1630,14 +1630,14 @@ msgstr "缓衝区大小" msgid "Buffer size for every connection (kB)" msgstr "每一個連接的缓衝区大小(kB)" -msgid "Handshake Timeout" -msgstr "握手超時 " - msgid "Idle Timeout" -msgstr "空闲超時 " +msgstr "空闲超時" -msgid "Hop Interval" -msgstr "端口跳跃時間 " +msgid "Hop Interval(second)" +msgstr "端口跳躍間隔(秒)" + +msgid "Supports a fixed value or a random range (e.g., 30, 5-30), minimum 5." +msgstr "支援固定值或隨機範圍(如 30 或 5-30),最小 5 秒。" msgid "HeartbeatPeriod(second)" msgstr "心跳周期(單位:秒)" diff --git a/luci-app-passwall2/root/usr/share/passwall2/app.sh b/luci-app-passwall2/root/usr/share/passwall2/app.sh index b45e0401..1f5b73eb 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -1169,6 +1169,7 @@ start() { export XRAY_LOCATION_ASSET=$V2RAY_LOCATION_ASSET export ENABLE_DEPRECATED_GEOSITE=true export ENABLE_DEPRECATED_GEOIP=true + export SS_SYSTEM_DNS_RESOLVER_FORCE_BUILTIN=1 ulimit -n 65535 start_haproxy start_socks @@ -1237,6 +1238,7 @@ stop() { pgrep -af "${CONFIG}/" | awk '! /app\.sh|subscribe\.lua|rule_update\.lua|tasks\.sh|server_app\.lua|ujail/{print $1}' | xargs kill -9 >/dev/null 2>&1 unset V2RAY_LOCATION_ASSET unset XRAY_LOCATION_ASSET + unset SS_SYSTEM_DNS_RESOLVER_FORCE_BUILTIN stop_crontab rm -rf $GLOBAL_DNSMASQ_CONF rm -rf $GLOBAL_DNSMASQ_CONF_PATH diff --git a/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.lua b/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.lua index c15d7d37..9fab4d10 100644 --- a/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.lua +++ b/luci-app-passwall2/root/usr/share/passwall2/helper_dnsmasq.lua @@ -272,7 +272,7 @@ function add_rule(var) local function process_address(address) if address == "engage.cloudflareclient.com" then return end if datatypes.hostname(address) then - set_domain_dns(address, fwd_dns) + --set_domain_dns(address, fwd_dns) set_domain_ipset(address, setflag_4 .. "passwall2_vps," .. setflag_6 .. "passwall2_vps6") end end diff --git a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index 624d2ecb..7a2ae59e 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -1216,10 +1216,8 @@ local function processData(szType, content, add_mode, group) result.httpupgrade_host = params.host result.httpupgrade_path = params.path end - result.encryption = params.encryption or "none" - - result.flow = params.flow and params.flow:gsub("-udp443", "") or nil + result.flow = params.flow result.tls = "0" if params.security == "tls" or params.security == "reality" then diff --git a/momo/Makefile b/momo/Makefile index 8dbcd7c1..21f165b5 100644 --- a/momo/Makefile +++ b/momo/Makefile @@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=momo PKG_VERSION:=2026.03.29 -PKG_RELEASE:=4 +PKG_RELEASE:=5 PKG_LICENSE:=GPL-3.0+ PKG_MAINTAINER:=Joseph Mory diff --git a/momo/files/momo.conf b/momo/files/momo.conf index a03a832b..15710b93 100644 --- a/momo/files/momo.conf +++ b/momo/files/momo.conf @@ -8,6 +8,13 @@ config config 'config' option 'test_profile' '1' option 'core_only' '0' +config log 'log' + option 'log_cleanup_enabled' '0' + option 'log_cleanup_cron_expression' '0 4 * * *' + option 'log_cleanup_size_enabled' '0' + option 'log_cleanup_size_check_cron_expression' '*/30 * * * *' + option 'log_cleanup_size_mb' '50' + config procd 'procd' option 'fast_reload' '0' diff --git a/momo/files/momo.init b/momo/files/momo.init index 4b6aabba..e3a11d2e 100644 --- a/momo/files/momo.init +++ b/momo/files/momo.init @@ -9,6 +9,8 @@ PROG="/usr/bin/sing-box" . "$IPKG_INSTROOT/etc/momo/scripts/include.sh" extra_command 'update_subscription' 'Update subscription by section id' +extra_command 'cleanup_logs' 'Cleanup logs immediately' +extra_command 'check_log_cleanup' 'Cleanup logs if size threshold is reached' boot_func() { # prepare files @@ -56,11 +58,17 @@ start_service() { # get config ## app config local scheduled_restart cron_expression profile test_profile core_only + local log_cleanup_enabled log_cleanup_cron_expression log_cleanup_size_enabled log_cleanup_size_check_cron_expression log_cleanup_size_mb config_get_bool scheduled_restart "config" "scheduled_restart" 0 config_get cron_expression "config" "cron_expression" config_get profile "config" "profile" config_get_bool test_profile "config" "test_profile" 0 config_get_bool core_only "config" "core_only" 0 + config_get_bool log_cleanup_enabled "log" "log_cleanup_enabled" 0 + config_get log_cleanup_cron_expression "log" "log_cleanup_cron_expression" + config_get_bool log_cleanup_size_enabled "log" "log_cleanup_size_enabled" 0 + config_get log_cleanup_size_check_cron_expression "log" "log_cleanup_size_check_cron_expression" + config_get log_cleanup_size_mb "log" "log_cleanup_size_mb" 0 ## procd config ### general local fast_reload @@ -194,9 +202,23 @@ start_service() { procd_close_instance # cron + local cron_reload; cron_reload=0 if [ "$scheduled_restart" = 1 ] && [ -n "$cron_expression" ]; then log "App" "Set scheduled restart." - echo "$cron_expression /etc/init.d/momo restart #momo" >> "/etc/crontabs/root" + echo "$cron_expression /etc/init.d/momo restart #momo_scheduled_restart" >> "/etc/crontabs/root" + cron_reload=1 + fi + if [ "$log_cleanup_enabled" = 1 ] && [ -n "$log_cleanup_cron_expression" ]; then + log "Log" "Set scheduled log cleanup." + echo "$log_cleanup_cron_expression /etc/init.d/momo cleanup_logs > /dev/null 2>&1 #momo_log_cleanup_time" >> "/etc/crontabs/root" + cron_reload=1 + fi + if [ "$log_cleanup_size_enabled" = 1 ] && [ -n "$log_cleanup_size_check_cron_expression" ] && [ "${log_cleanup_size_mb:-0}" -gt 0 ]; then + log "Log" "Set size-based log cleanup check." + echo "$log_cleanup_size_check_cron_expression /etc/init.d/momo check_log_cleanup > /dev/null 2>&1 #momo_log_cleanup_size" >> "/etc/crontabs/root" + cron_reload=1 + fi + if [ "$cron_reload" = 1 ]; then /etc/init.d/cron restart fi # set started flag @@ -405,6 +427,46 @@ cleanup() { /etc/init.d/cron restart } +cleanup_logs() { + prepare_files + run_log_cleanup "scheduled trigger" +} + +check_log_cleanup() { + prepare_files + config_load momo + + local log_cleanup_size_enabled log_cleanup_size_mb total_size_bytes threshold_size_bytes + config_get_bool log_cleanup_size_enabled "log" "log_cleanup_size_enabled" 0 + config_get log_cleanup_size_mb "log" "log_cleanup_size_mb" 0 + + if [ "$log_cleanup_size_enabled" != 1 ] || [ "${log_cleanup_size_mb:-0}" -le 0 ]; then + return + fi + + total_size_bytes=$(get_total_log_size) + threshold_size_bytes=$((log_cleanup_size_mb * 1024 * 1024)) + + if [ "$total_size_bytes" -lt "$threshold_size_bytes" ]; then + return + fi + + run_log_cleanup "size threshold ${log_cleanup_size_mb} MB reached" "$total_size_bytes" +} + +run_log_cleanup() { + local reason previous_size + reason="$1" + previous_size="$2" + + if [ -z "$previous_size" ]; then + previous_size=$(get_total_log_size) + fi + + clear_log + log "Log" "Cleanup executed: ${reason}. Previous total size: $(format_filesize "$previous_size")." +} + update_subscription() { local subscription_section; subscription_section="$1" if [ -z "$subscription_section" ]; then diff --git a/momo/files/scripts/include.sh b/momo/files/scripts/include.sh index feac9a8a..18e8e6c2 100644 --- a/momo/files/scripts/include.sh +++ b/momo/files/scripts/include.sh @@ -118,6 +118,9 @@ prepare_files() { if [ ! -f "$CORE_LOG_PATH" ]; then touch "$CORE_LOG_PATH" fi + if [ ! -f "$DEBUG_LOG_PATH" ]; then + touch "$DEBUG_LOG_PATH" + fi if [ ! -d "$TEMP_DIR" ]; then mkdir -p "$TEMP_DIR" fi @@ -126,6 +129,26 @@ prepare_files() { clear_log() { echo -n > "$APP_LOG_PATH" echo -n > "$CORE_LOG_PATH" + echo -n > "$DEBUG_LOG_PATH" +} + +get_filesize() { + local path; path="$1" + if [ ! -f "$path" ]; then + echo 0 + return + fi + wc -c < "$path" | tr -d '[:space:]' +} + +get_total_log_size() { + local total_size path path_size + total_size=0 + for path in "$APP_LOG_PATH" "$CORE_LOG_PATH" "$DEBUG_LOG_PATH"; do + path_size=$(get_filesize "$path") + total_size=$((total_size + path_size)) + done + echo "$total_size" } log() { diff --git a/momo/files/uci-defaults/migrate.sh b/momo/files/uci-defaults/migrate.sh index 2f47856a..20e3ce4f 100644 --- a/momo/files/uci-defaults/migrate.sh +++ b/momo/files/uci-defaults/migrate.sh @@ -25,6 +25,45 @@ procd=$(uci -q get momo.procd); [ -z "$procd" ] && { dummy_device=$(uci -q get momo.routing.dummy_device); [ -z "$dummy_device" ] && uci set momo.routing.dummy_device=momo-dummy +# since v1.1.2 + +section_log=$(uci -q get momo.log); [ -z "$section_log" ] && uci set momo.log=log + +log_cleanup_enabled=$(uci -q get momo.log.log_cleanup_enabled) +[ -z "$log_cleanup_enabled" ] && { + log_cleanup_enabled=$(uci -q get momo.config.log_cleanup_enabled) + [ -n "$log_cleanup_enabled" ] && uci set momo.log.log_cleanup_enabled=$log_cleanup_enabled || uci set momo.log.log_cleanup_enabled=0 +} +uci -q del momo.config.log_cleanup_enabled + +log_cleanup_cron_expression=$(uci -q get momo.log.log_cleanup_cron_expression) +[ -z "$log_cleanup_cron_expression" ] && { + log_cleanup_cron_expression=$(uci -q get momo.config.log_cleanup_cron_expression) + [ -n "$log_cleanup_cron_expression" ] && uci set momo.log.log_cleanup_cron_expression="$log_cleanup_cron_expression" || uci set momo.log.log_cleanup_cron_expression='0 4 * * *' +} +uci -q del momo.config.log_cleanup_cron_expression + +log_cleanup_size_enabled=$(uci -q get momo.log.log_cleanup_size_enabled) +[ -z "$log_cleanup_size_enabled" ] && { + log_cleanup_size_enabled=$(uci -q get momo.config.log_cleanup_size_enabled) + [ -n "$log_cleanup_size_enabled" ] && uci set momo.log.log_cleanup_size_enabled=$log_cleanup_size_enabled || uci set momo.log.log_cleanup_size_enabled=0 +} +uci -q del momo.config.log_cleanup_size_enabled + +log_cleanup_size_check_cron_expression=$(uci -q get momo.log.log_cleanup_size_check_cron_expression) +[ -z "$log_cleanup_size_check_cron_expression" ] && { + log_cleanup_size_check_cron_expression=$(uci -q get momo.config.log_cleanup_size_check_cron_expression) + [ -n "$log_cleanup_size_check_cron_expression" ] && uci set momo.log.log_cleanup_size_check_cron_expression="$log_cleanup_size_check_cron_expression" || uci set momo.log.log_cleanup_size_check_cron_expression='*/30 * * * *' +} +uci -q del momo.config.log_cleanup_size_check_cron_expression + +log_cleanup_size_mb=$(uci -q get momo.log.log_cleanup_size_mb) +[ -z "$log_cleanup_size_mb" ] && { + log_cleanup_size_mb=$(uci -q get momo.config.log_cleanup_size_mb) + [ -n "$log_cleanup_size_mb" ] && uci set momo.log.log_cleanup_size_mb=$log_cleanup_size_mb || uci set momo.log.log_cleanup_size_mb=50 +} +uci -q del momo.config.log_cleanup_size_mb + # commit uci commit momo