diff --git a/doc/lucky1.png b/doc/lucky1.png deleted file mode 100644 index a5b41b6e..00000000 Binary files a/doc/lucky1.png and /dev/null differ diff --git a/doc/lucky2.png b/doc/lucky2.png deleted file mode 100644 index ba4c026f..00000000 Binary files a/doc/lucky2.png and /dev/null differ diff --git a/doc/lucky3.png b/doc/lucky3.png deleted file mode 100644 index 6fa7982f..00000000 Binary files a/doc/lucky3.png and /dev/null differ diff --git a/doc/taskplan1.png b/doc/taskplan1.png new file mode 100644 index 00000000..1f8db7be Binary files /dev/null and b/doc/taskplan1.png differ diff --git a/doc/taskplan2.png b/doc/taskplan2.png new file mode 100644 index 00000000..edb45d6d Binary files /dev/null and b/doc/taskplan2.png differ diff --git a/doc/taskplan3.png b/doc/taskplan3.png new file mode 100644 index 00000000..d4794702 Binary files /dev/null and b/doc/taskplan3.png differ diff --git a/doc/view.png b/doc/view.png new file mode 100644 index 00000000..169e112f Binary files /dev/null and b/doc/view.png differ diff --git a/doc/view2.png b/doc/view2.png new file mode 100644 index 00000000..9058c632 Binary files /dev/null and b/doc/view2.png differ 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 b650fc86..92aed02e 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 @@ -188,8 +188,8 @@ domain_list.validate = function(self, value) tmp_host = host:gsub("full:", "") elseif host:find("geosite:") and host:find("geosite:") == 1 then flag = 0 - elseif host:find("ext:") and host:find("ext:") == 1 then - flag = 0 +-- elseif host:find("ext:") and host:find("ext:") == 1 then +-- flag = 0 elseif host:find("rule-set:", 1, true) == 1 or host:find("rs:") == 1 then local w = host:sub(host:find(":") + 1, #host) if w:find("local:") == 1 or w:find("remote:") == 1 then @@ -230,7 +230,7 @@ ip_list.validate = function(self, value) string.gsub(value, "[^\r\n]+", function(w) table.insert(ipmasks, w) end) for index, ipmask in ipairs(ipmasks) do if ipmask:find("geoip:") and ipmask:find("geoip:") == 1 and not ipmask:find("%s") then - elseif ipmask:find("ext:") and ipmask:find("ext:") == 1 and not ipmask:find("%s") then +-- elseif ipmask:find("ext:") and ipmask:find("ext:") == 1 and not ipmask:find("%s") then elseif ipmask:find("rule-set:", 1, true) == 1 or ipmask:find("rs:") == 1 then local w = ipmask:sub(ipmask:find(":") + 1, #ipmask) if w:find("local:") == 1 or w:find("remote:") == 1 then diff --git a/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm b/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm index c8a05439..b56d08da 100644 --- a/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm +++ b/luci-app-passwall/luasrc/view/passwall/node_config/link_share_man.htm @@ -691,12 +691,40 @@ local current_node = map:get(section) params += opt.query("congestion_control", dom_prefix + "naive_congestion_control"); } + params += "#" + encodeURI(v_alias.value); + if (params[0] == "&") { + params = params.substring(1); + } + url += params; + } else if (v_type === "sing-box" && opt.get(dom_prefix + "protocol").value === "snell") { + protocol = "snell"; + var v_userkey = opt.get(dom_prefix + "password"); + var v_psk = opt.get(dom_prefix + "snell_psk"); + var v_port = opt.get(dom_prefix + "port"); + url = encodeURIComponent(v_psk.value) + + "@" + _address + + ":" + v_port.value + "?"; + + var params = "psk=" + encodeURIComponent(v_psk.value); + if (v_userkey.value !== "") { + params += "&userkey=" + encodeURIComponent(v_userkey.value); + } + params += opt.query("version", dom_prefix + "snell_version"); + if (opt.get(dom_prefix + "snell_version").value === '4') { + params += opt.query("obfs", dom_prefix + "snell_obfs_mode"); + params += opt.query("obfs-host", dom_prefix + "snell_obfs_host"); + } else { + params += opt.query("mode", dom_prefix + "snell_mode"); + } + params += opt.query("reuse", dom_prefix + "snell_reuse"); + params += "#" + encodeURI(v_alias.value); if (params[0] == "&") { params = params.substring(1); } url += params; } + if (url) { url = protocol.toLowerCase() + "://" + url; return url; @@ -1705,6 +1733,37 @@ local current_node = map:get(section) opt.set('remarks', decodeURIComponent(hash.substr(1))); } } + if (link_type === "snell") { + if (has_singbox) { + dom_prefix = "singbox_"; + opt.set('type', "sing-box"); + } + opt.set(dom_prefix + 'protocol', "snell"); + var m = parseNodeUrl(link); + opt.set(dom_prefix + 'address', unbracketIP(m.hostname)); + opt.set(dom_prefix + 'port', m.port || "443"); + var queryParam = {}; + if (m.search.length > 1) { + var query = m.search.replace('/?', '?').split('?') + var queryParams = query[1]; + var queryArray = queryParams.split('&'); + var params; + for (i = 0; i < queryArray.length; i++) { + params = queryArray[i].split('='); + queryParam[decodeURIComponent(params[0]).toLowerCase()] = decodeURIComponent(params[1] || ''); + } + } + opt.set(dom_prefix + 'password', queryParam.userkey || ''); + opt.set(dom_prefix + 'snell_psk', queryParam.psk || m.passwd || ''); + opt.set(dom_prefix + 'snell_version', queryParam.version || '4'); + opt.set(dom_prefix + 'snell_reuse', queryParam.reuse === '1'); + opt.set(dom_prefix + 'snell_obfs_mode', queryParam.obfs || 'none'); + opt.set(dom_prefix + 'snell_obfs_host', queryParam['obfs-host'] || queryParam.obfs_host || ''); + opt.set(dom_prefix + 'snell_mode', queryParam.mode || 'default'); + if (m.hash) { + opt.set('remarks', decodeURIComponent(m.hash.substr(1))); + } + } if (switch_type) { sessionStorage.setItem("fromUrl", JSON.stringify({ diff --git a/luci-app-passwall/po/zh-cn/passwall.po b/luci-app-passwall/po/zh-cn/passwall.po index ffb4266e..2da388cf 100644 --- a/luci-app-passwall/po/zh-cn/passwall.po +++ b/luci-app-passwall/po/zh-cn/passwall.po @@ -1452,7 +1452,7 @@ msgid "Private Key" msgstr "私钥" msgid "Pre shared key" -msgstr "额外的对称加密密钥" +msgstr "预共享密钥" msgid "Allowed IPs" msgstr "允许的 IP" diff --git a/luci-app-passwall/root/usr/share/passwall/clash_subconverter.lua b/luci-app-passwall/root/usr/share/passwall/clash_subconverter.lua index 07d16152..4dcbe398 100644 --- a/luci-app-passwall/root/usr/share/passwall/clash_subconverter.lua +++ b/luci-app-passwall/root/usr/share/passwall/clash_subconverter.lua @@ -513,6 +513,42 @@ local function encode_ssr(node) return 0, "ssr://" .. base64(link) end +-- snell +local function encode_snell(node) + local err_msg + local obfs = node["obfs-opts"] + if obfs and obfs.mode ~= "http" and obfs.mode ~= "none" then + err_msg = obfs.mode + end + if err_msg then + err_msg = "订阅转换 → 丢弃 Snell 节点:" .. (node.name or "") .. ",因 Sing-Box 不支持 Snell + " .. err_msg + return 1, err_msg + end + local version = node.version and tonumber(node.version) or 4 + version = (version == 5) and 4 or version + if version < 4 then + err_msg = "订阅转换 → 丢弃 Snell 节点:" .. (node.name or "") .. ",因 Sing-Box 不支持 Snell 版本小于 4" + return 1, err_msg + end + + local link = "snell://" .. host_format(node.server) .. ":" .. node.port + local p = {} + + if node.psk then table.insert(p, "psk=" .. urlencode(node.psk)) end + table.insert(p, "version=" .. version) + if obfs.mode == "http" then + table.insert(p, "obfs=http") + if obfs.host then table.insert(p, "obfs-host=" .. urlencode(obfs.host)) end + end + table.insert(p, "reuse=" .. (node.reuse and "1" or "0")) + + if #p > 0 then + link = link .. "?" .. table.concat(p, "&") + end + + return 0, link .. "#" .. urlencode(node.name or "") +end + local function encode_node(node) if (not node.type) or (not node.name) then return nil end @@ -529,6 +565,7 @@ local function encode_node(node) elseif t == "tuic" then return encode_tuic(node) elseif t == "anytls" then return encode_anytls(node) elseif t == "ssr" then return encode_ssr(node) + elseif t == "snell" then return encode_snell(node) else api.log("订阅转换 → 丢弃不支持的节点:" .. node.name .. ",节点类型:" .. t) end end diff --git a/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/luci-app-passwall/root/usr/share/passwall/subscribe.lua index 61b840d3..dc468860 100755 --- a/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -1628,6 +1628,62 @@ local function processData(szType, content, add_mode, group, sub_cfg) result.naive_quic = "1" result.naive_congestion_control = params.congestion_control or "bbr" end + elseif szType == "snell" then + if has_singbox then + result.type = 'sing-box' + result.protocol = "snell" + else + log("跳过 Snell 节点,因未安装 Snell 核心程序 Sing-box 1.14。") + return nil + end + + local alias = "" + if content:find("#") then + local idx_sp = content:find("#") + alias = content:sub(idx_sp + 1, -1) + content = content:sub(0, idx_sp - 1) + end + result.remarks = UrlDecode(alias) + local Info = content + if content:find("@") then + local info = split(content, "@") + result.snell_psk = UrlDecode(info[1]) + Info = info[2] + end + Info = (Info or ""):gsub("/%?", "?") + local query = split(Info, "%?") + local host_port = query[1] + local params = {} + for _, v in pairs(split(query[2], '&')) do + local s = v:find("=", 1, true) + if s and s > 1 then + params[UrlDecode(v:sub(1, s - 1)):lower()] = UrlDecode(v:sub(s + 1)) + end + end + -- [2001:4860:4860::8888]:443 + -- 8.8.8.8:443 + result.port = "443" + if host_port:find(":") then + local sp = split(host_port, ":") + result.port = sp[#sp] + if api.is_ipv6addrport(host_port) then + result.address = api.get_ipv6_only(host_port) + else + result.address = sp[1] + end + else + result.address = host_port + end + result.snell_psk = params.psk or result.snell_psk + result.password = params.userkey + result.snell_version = params.version or "4" + if result.snell_version == "4" then + result.snell_obfs_mode = params.obfs or "none" + result.snell_obfs_host = params['obfs-host'] or params.obfs_host + else + result.snell_mode = params.mode or "default" + end + result.snell_reuse = (params.reuse == "1") and "1" or "0" else log("暂时不支持 " .. szType .. " 类型的节点订阅,跳过此节点。") return nil diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/shunt_rules.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/shunt_rules.lua index 7194da87..657b5b07 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/shunt_rules.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/shunt_rules.lua @@ -191,8 +191,8 @@ domain_list.validate = function(self, value) tmp_host = host:gsub("full:", "") elseif host:find("geosite:") and host:find("geosite:") == 1 then flag = 0 - elseif host:find("ext:") and host:find("ext:") == 1 then - flag = 0 +-- elseif host:find("ext:") and host:find("ext:") == 1 then +-- flag = 0 elseif host:find("rule-set:", 1, true) == 1 or host:find("rs:") == 1 then local w = host:sub(host:find(":") + 1, #host) if w:find("local:") == 1 or w:find("remote:") == 1 then @@ -233,7 +233,7 @@ ip_list.validate = function(self, value) string.gsub(value, "[^\r\n]+", function(w) table.insert(ipmasks, w) end) for index, ipmask in ipairs(ipmasks) do if ipmask:find("geoip:") and ipmask:find("geoip:") == 1 and not ipmask:find("%s") then - elseif ipmask:find("ext:") and ipmask:find("ext:") == 1 and not ipmask:find("%s") then +-- elseif ipmask:find("ext:") and ipmask:find("ext:") == 1 and not ipmask:find("%s") then elseif ipmask:find("rule-set:", 1, true) == 1 or ipmask:find("rs:") == 1 then local w = ipmask:sub(ipmask:find(":") + 1, #ipmask) if w:find("local:") == 1 or w:find("remote:") == 1 then diff --git a/luci-app-syncthing/Makefile b/luci-app-syncthing/Makefile deleted file mode 100644 index 2219fcb2..00000000 --- a/luci-app-syncthing/Makefile +++ /dev/null @@ -1,22 +0,0 @@ -# Copyright (C) 2020 Gyj1109 -# 适配 OpenWrt 25.12 修改版 - -include $(TOPDIR)/rules.mk - -PKG_NAME:=luci-app-syncthing -PKG_VERSION:=1.0 -PKG_RELEASE:=3 - -LUCI_TITLE:=LuCI support for Syncthing -LUCI_PKGARCH:=all -# 适配 25.12:确保安装了 syncthing 后,LuCI 界面能正确拉起 -LUCI_DEPENDS:=+syncthing - -include $(TOPDIR)/feeds/luci/luci.mk - -# 明确定义配置文件的归属,这对 25.12 的 apk 管理器非常重要 -define Package/$(PKG_NAME)/conffiles -/etc/config/syncthing -endef - -$(eval $(call BuildPackage,$(PKG_NAME))) diff --git a/luci-app-syncthing/README.md b/luci-app-syncthing/README.md deleted file mode 100644 index b07298c1..00000000 --- a/luci-app-syncthing/README.md +++ /dev/null @@ -1,2 +0,0 @@ -# luci-app-syncthing -在Potat0000源码基础上进行了汉化优化,官方openwrt23.05.3编译后可使用 diff --git a/luci-app-syncthing/luasrc/controller/syncthing.lua b/luci-app-syncthing/luasrc/controller/syncthing.lua deleted file mode 100644 index ee2ca7ef..00000000 --- a/luci-app-syncthing/luasrc/controller/syncthing.lua +++ /dev/null @@ -1,17 +0,0 @@ -module("luci.controller.syncthing", package.seeall) - -function index() - if not nixio.fs.access("/etc/config/syncthing") then - return - end - - entry({"admin", "services", "syncthing"}, cbi("syncthing"), _("文件同步"), 10).dependent = true - entry({"admin", "services", "syncthing", "status"}, call("act_status")).leaf = true -end - -function act_status() - local e = {} - e.running = luci.sys.call("pgrep syncthing >/dev/null") == 0 - luci.http.prepare_content("application/json") - luci.http.write_json(e) -end diff --git a/luci-app-syncthing/luasrc/model/cbi/syncthing.lua b/luci-app-syncthing/luasrc/model/cbi/syncthing.lua deleted file mode 100644 index 324ea054..00000000 --- a/luci-app-syncthing/luasrc/model/cbi/syncthing.lua +++ /dev/null @@ -1,48 +0,0 @@ -require("nixio.fs") - -m = Map("syncthing", translate("Syncthing同步工具")) - -m:section(SimpleSection).template = "syncthing/syncthing_status" - -s = m:section(TypedSection, "syncthing") - -s.anonymous = true - -o = s:option(Flag, "enabled", translate("启用")) -o.default = 0 -o.rmempty = false - -gui_address = s:option(Value, "gui_address", translate("GUI访问地址")) -gui_address.description = translate("使用0.0.0.0以监控所有访问。") -gui_address.default = "http://0.0.0.0:8384" -gui_address.placeholder = "http://0.0.0.0:8384" -gui_address.rmempty = false - -home = s:option(Value, "home", translate("配置文件目录")) -home.description = translate("只有保存在/etc/syncthing中的配置会自动备份!") -home.default = "/etc/syncthing" -home.placeholder = "/etc/syncthing" -home.rmempty = false - -user = s:option(ListValue, "user", translate("用户")) -user.description = translate("默认是syncthing,但这可能会导致权限被拒绝。Syncthing官方不建议以root身份运行。") -user:value("", translate("syncthing")) -for u in luci.util.execi("cat /etc/passwd | cut -d ':' -f1") do - user:value(u) -end - -macprocs = s:option(Value, "macprocs", translate("线程限制")) -macprocs.description = translate("0表示匹配CPU数量(默认),>0表示显式指定并发数。") -macprocs.default = "0" -macprocs.placeholder = "0" -macprocs.datatype = "range(0,32)" -macprocs.rmempty = false - -nice = s:option(Value, "nice", translate("优先级")) -nice.description = translate("显式指定优先级值。0是最高,19是最低。(暂时不允许设置负值)") -nice.default = "19" -nice.placeholder = "19" -nice.datatype = "range(0,19)" -nice.rmempty = false - -return m diff --git a/luci-app-syncthing/luasrc/view/syncthing/syncthing_status.htm b/luci-app-syncthing/luasrc/view/syncthing/syncthing_status.htm deleted file mode 100644 index 566cc020..00000000 --- a/luci-app-syncthing/luasrc/view/syncthing/syncthing_status.htm +++ /dev/null @@ -1,27 +0,0 @@ - - -
-

- <%:正在收集数据...%> -

-
diff --git a/luci-app-syncthing/root/etc/uci-defaults/luci-syncthing b/luci-app-syncthing/root/etc/uci-defaults/luci-syncthing deleted file mode 100644 index 3adb7997..00000000 --- a/luci-app-syncthing/root/etc/uci-defaults/luci-syncthing +++ /dev/null @@ -1,12 +0,0 @@ -#!/bin/sh -touch /etc/config/syncthing - -uci -q batch <<-EOF >/dev/null - delete ucitrack.@syncthing[-1] - add ucitrack syncthing - set ucitrack.@syncthing[-1].exec='/etc/init.d/syncthing stop && /etc/init.d/syncthing start' - commit ucitrack -EOF -# remove LuCI cache -rm -f /tmp/luci* -exit 0 diff --git a/luci-app-syncthing/root/usr/share/rpcd/acl.d/luci-app-syncthing.json b/luci-app-syncthing/root/usr/share/rpcd/acl.d/luci-app-syncthing.json deleted file mode 100644 index 9fc9cc54..00000000 --- a/luci-app-syncthing/root/usr/share/rpcd/acl.d/luci-app-syncthing.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "luci-app-syncthing": { - "description": "Grant UCI access for luci-app-syncthing", - "read": { - "uci": [ "syncthing" ] - }, - "write": { - "uci": [ "syncthing" ] - } - } -}