diff --git a/luci-app-easytier/Makefile b/luci-app-easytier/Makefile index 6c4ce31b..43ca199c 100644 --- a/luci-app-easytier/Makefile +++ b/luci-app-easytier/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk -include $(dir $(lastword $(MAKEFILE_LIST)))../version.mk PKG_VERSION:=$(or $(EASYTIER_VERSION),2.6.4) -PKG_RELEASE:=9 +PKG_RELEASE:=10 LUCI_TITLE:=LuCI support for EasyTier LUCI_DEPENDS:=+kmod-tun +easytier +luci-compat diff --git a/luci-app-easytier/luasrc/controller/easytier.lua b/luci-app-easytier/luasrc/controller/easytier.lua index 395c67a4..51e3594a 100644 --- a/luci-app-easytier/luasrc/controller/easytier.lua +++ b/luci-app-easytier/luasrc/controller/easytier.lua @@ -147,7 +147,7 @@ function act_status() end e.no_tun = uci:get_first("easytier", "easytier", "no_tun") == "1" - e.dev_name = uci:get_first("easytier", "easytier", "dev_name") or "tun0" + e.dev_name = uci:get_first("easytier", "easytier", "tunname") or "tun0" luci.http.prepare_content("application/json") luci.http.write_json(e) diff --git a/luci-app-easytier/luasrc/view/easytier/easytier_cli.htm b/luci-app-easytier/luasrc/view/easytier/easytier_cli.htm index 38b71400..ed9ae4eb 100644 --- a/luci-app-easytier/luasrc/view/easytier/easytier_cli.htm +++ b/luci-app-easytier/luasrc/view/easytier/easytier_cli.htm @@ -1232,6 +1232,18 @@ function refreshConnInfo() { } } }; + xhr.onerror = function() { + isRefreshing = false; + btn.disabled = false; + btn.classList.remove('loading'); + btnText.textContent = originalText; + }; + xhr.onabort = function() { + isRefreshing = false; + btn.disabled = false; + btn.classList.remove('loading'); + btnText.textContent = originalText; + }; xhr.send(); } @@ -1496,7 +1508,7 @@ function loadContributors() { // 自动刷新 XHR.poll(5, '<%=url("admin", "vpn", "easytier", "api_conninfo")%>', null, function(x, data) { - if (!isRefreshing) { + if (!isRefreshing && data) { updateConnInfo(data); } }); diff --git a/luci-app-easytier/luasrc/view/easytier/easytier_status.htm b/luci-app-easytier/luasrc/view/easytier/easytier_status.htm index c49c4924..9608eefb 100644 --- a/luci-app-easytier/luasrc/view/easytier/easytier_status.htm +++ b/luci-app-easytier/luasrc/view/easytier/easytier_status.htm @@ -1075,6 +1075,7 @@ function updateTunInterface(coreRunning, noTun, devName) { var firstLoad = true; XHR.poll(3, '<%=url("admin", "vpn", "easytier", "api_status")%>', null, function(x, data) { + if (!data) return; updateStatus(data); updateTunInterface(data.crunning, data.no_tun, data.dev_name); diff --git a/luci-app-passwall/Makefile b/luci-app-passwall/Makefile index 2d0d020b..2c773e27 100644 --- a/luci-app-passwall/Makefile +++ b/luci-app-passwall/Makefile @@ -8,7 +8,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall PKG_VERSION:=26.5.20 -PKG_RELEASE:=140 +PKG_RELEASE:=141 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ 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 4730c274..032277ad 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 @@ -341,13 +341,28 @@ o:depends({ [_n("protocol")] = "vless" }) ---- [[hysteria2]] 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:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) 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:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) + +o = s:option(Flag, _n("hysteria2_realms"), translate("Realms")) +o.default = "0" +if api.compare_versions(xray_version, ">", "26.5.9") then + o:depends({ [_n("protocol")] = "hysteria2"}) +else + o:depends({ [_n("protocol")] = "__hide"}) +end + +o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name") +o:depends({ [_n("hysteria2_realms")] = "1" }) + +o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN")) +o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" } +o:depends({ [_n("hysteria2_realms")] = "1" }) o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) o.password = true @@ -438,7 +453,7 @@ end o = s:option(Flag, _n("ech"), translate("ECH")) o.default = "0" o:depends({ [_n("tls")] = true, [_n("reality")] = false }) -o:depends({ [_n("protocol")] = "hysteria2" }) +o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) o = s:option(TextValue, _n("ech_config"), translate("ECH Config")) o.default = "" @@ -715,7 +730,7 @@ o:depends({ [_n("protocol")] = "vless" }) o:depends({ [_n("protocol")] = "trojan" }) o:depends({ [_n("protocol")] = "shadowsocks" }) o:depends({ [_n("protocol")] = "wireguard" }) -o:depends({ [_n("protocol")] = "hysteria2" }) +o:depends({ [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) o = s:option(TextValue, _n("finalmask"), " ") o:depends({ [_n("use_finalmask")] = true }) @@ -788,10 +803,14 @@ local protocols = s.fields[_n("protocol")].keylist if #protocols > 0 then for i, v in ipairs(protocols) do if not v:find("^_") then - s.fields[_n("address")]:depends({ [_n("protocol")] = v }) - s.fields[_n("port")]:depends({ [_n("protocol")] = v }) - s.fields[_n("domain_resolver")]:depends({ [_n("protocol")] = v }) - s.fields[_n("domain_strategy")]:depends({ [_n("protocol")] = v }) + local depends_condition = { [_n("protocol")] = v } + if v == "hysteria2" then + depends_condition[_n("hysteria2_realms")] = false + end + s.fields[_n("address")]:depends(depends_condition) + s.fields[_n("port")]:depends(depends_condition) + s.fields[_n("domain_resolver")]:depends(depends_condition) + s.fields[_n("domain_strategy")]:depends(depends_condition) if v ~= "hysteria2" then s.fields[_n("tcp_fast_open")]:depends({ [_n("protocol")] = v }) @@ -814,7 +833,7 @@ if not load_shunt_options then o:value("2", translate("Landing Node")) o1 = s:option(ListValue, _n("preproxy_node"), translate("Preproxy Node"), translate("Only support a layer of proxy.")) - o1:depends({ [_n("chain_proxy")] = "1" }) + o1:depends({ [_n("chain_proxy")] = "1", [_n("hysteria2_realms")] = false }) o1.template = appname .. "/cbi/nodes_listvalue" o1.group = {} @@ -826,7 +845,7 @@ if not load_shunt_options then end o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy.")) - o2:depends({ [_n("chain_proxy")] = "2" }) + o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false }) o2.template = appname .. "/cbi/nodes_listvalue" o2.group = {} diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ray.lua b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ray.lua index 437f11c7..9db30b73 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ray.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/server/type/ray.lua @@ -127,6 +127,17 @@ o:value("xtls-rprx-vision") o:depends({ [_n("protocol")] = "vless" }) ---- [[ hysteria2 ]] +o = s:option(Flag, _n("hysteria2_realms"), translate("Realms")) +o.default = "0" +o:depends({ [_n("protocol")] = "hysteria2"}) + +o = s:option(Value, _n("hysteria2_realm_url"), translate("Realm URL"), translate("Example:") .. "realm://public@realm.hy2.io/your-realm-name") +o:depends({ [_n("hysteria2_realms")] = "1" }) + +o = s:option(DynamicList, _n("hysteria2_realm_stun"), translate("Realm STUN")) +o.default = { "stun.sip.us:3478", "stun.nextcloud.com:3478", "global.stun.twilio.com:3478" } +o:depends({ [_n("hysteria2_realms")] = "1" }) + o = s:option(Value, _n("hysteria2_auth_password"), translate("Auth Password")) o.password = true o:depends({ [_n("protocol")] = "hysteria2"}) @@ -210,7 +221,8 @@ function o.write(self, section, value) end o = s:option(ListValue, _n("alpn"), translate("alpn")) -o.default = "h2,http/1.1" +o.default = "default" +o:value("default", translate("Default")) o:value("h3") o:value("h2") o:value("h3,h2") @@ -375,7 +387,7 @@ o:depends({ [_n("custom")] = false, [_n("protocol")] = "vless" }) o:depends({ [_n("custom")] = false, [_n("protocol")] = "trojan" }) o:depends({ [_n("custom")] = false, [_n("protocol")] = "shadowsocks" }) o:depends({ [_n("custom")] = false, [_n("protocol")] = "wireguard" }) -o:depends({ [_n("custom")] = false, [_n("protocol")] = "hysteria2" }) +o:depends({ [_n("custom")] = false, [_n("protocol")] = "hysteria2", [_n("hysteria2_realms")] = false }) o = s:option(TextValue, _n("finalmask"), "FinalMask JSON") o:depends({ [_n("use_finalmask")] = true }) diff --git a/luci-app-passwall/luasrc/passwall/util_xray.lua b/luci-app-passwall/luasrc/passwall/util_xray.lua index edbe252c..ef3fd8db 100644 --- a/luci-app-passwall/luasrc/passwall/util_xray.lua +++ b/luci-app-passwall/luasrc/passwall/util_xray.lua @@ -44,8 +44,8 @@ function gen_outbound(flag, node, tag, proxy_table) local run_socks_instance = true if proxy_table ~= nil and type(proxy_table) == "table" then proxy_tag = proxy_table.tag or nil - fragment = proxy_table.fragment or nil - noise = proxy_table.noise or nil + fragment = (proxy_table.fragment and not node.hysteria2_realms) and true or nil + noise = (proxy_table.noise and not node.hysteria2_realms) and true or nil run_socks_instance = proxy_table.run_socks_instance end @@ -274,14 +274,35 @@ function gen_outbound(flag, node, tag, proxy_table) udp[#udp+1] = c finalmask.udp = udp elseif TP == "hysteria" then + local udp = {} if node.hysteria2_obfs_type and node.hysteria2_obfs_type ~= "" then - finalmask.udp = {{ + local o = { type = node.hysteria2_obfs_type, settings = node.hysteria2_obfs_password and { password = node.hysteria2_obfs_password } or nil - }} + } + udp[#udp+1] = o end + if node.hysteria2_realms then + local realm = api.parse_realm_uri(node.hysteria2_realm_url) + local url, stun + if realm then + if realm.token and realm.server_url and realm.realm_id then + url = "realm://" .. realm.token .. "@" .. realm.server_url .. "/" .. realm.realm_id + end + stun = realm.stun_servers or node.hysteria2_realm_stun + end + local r = { + type = "realm", + settings = { + url = url, + stunServers = stun + } + } + udp[#udp+1] = r + end + finalmask.udp = udp local up = tonumber(node.hysteria2_up_mbps) or 0 local down = tonumber(node.hysteria2_down_mbps) or 0 finalmask.quicParams = { @@ -704,14 +725,35 @@ function gen_config_server(node) udp[#udp+1] = c finalmask.udp = udp elseif node.transport == "hysteria" then + local udp = {} if node.hysteria2_obfs_type and node.hysteria2_obfs_type ~= "" then - finalmask.udp = {{ + local o = { type = node.hysteria2_obfs_type, settings = node.hysteria2_obfs_password and { password = node.hysteria2_obfs_password } or nil - }} + } + udp[#udp+1] = o end + if node.hysteria2_realms then + local realm = api.parse_realm_uri(node.hysteria2_realm_url) + local url, stun + if realm then + if realm.token and realm.server_url and realm.realm_id then + url = "realm://" .. realm.token .. "@" .. realm.server_url .. "/" .. realm.realm_id + end + stun = realm.stun_servers or node.hysteria2_realm_stun + end + local r = { + type = "realm", + settings = { + url = url, + stunServers = stun + } + } + udp[#udp+1] = r + end + finalmask.udp = udp local ignore = tonumber(node.hysteria2_ignore_client_bandwidth) == 1 local up = (not ignore) and tonumber(node.hysteria2_up_mbps) or 0 local down = (not ignore) and tonumber(node.hysteria2_down_mbps) or 0 @@ -742,7 +784,7 @@ function gen_config_server(node) } local alpn = {} - if node.alpn then + if node.alpn and node.alpn ~= "default" then string.gsub(node.alpn, '[^' .. "," .. ']+', function(w) table.insert(alpn, w) end) diff --git a/openwrt-alwaysonline/Makefile b/openwrt-alwaysonline/Makefile index 0a21fb80..62af59ce 100644 --- a/openwrt-alwaysonline/Makefile +++ b/openwrt-alwaysonline/Makefile @@ -8,12 +8,12 @@ PKG_NAME:=alwaysonline PKG_UPSTREAM_VERSION:=1.2.1 PKG_UPSTREAM_GITHASH:=206292ca68e4d6c81b215163a7bbd0cd2eb36860 PKG_VERSION:=$(PKG_UPSTREAM_VERSION)~$(call version_abbrev,$(PKG_UPSTREAM_GITHASH)) -PKG_RELEASE:=2 +PKG_RELEASE:=3 UCI_VERSION:=0.2025.01.25 PKG_SOURCE_PROTO:=git PKG_SOURCE_URL:=https://github.com/Jamesits/alwaysonline.git -PKG_SOURCE_VERSION:=c328927a0fac3ffc869a3dc04c33256cf0f3365c +PKG_SOURCE_VERSION:=eaba4daa34d1a759f1bd6a18e20b00928e09bbe8 PKG_MIRROR_HASH:=skip PKG_SOURCE_SUBDIR:=$(PKG_NAME)-$(PKG_UPSTREAM_VERSION) diff --git a/quickfile/Makefile b/quickfile/Makefile index ad65dac0..78fd31db 100644 --- a/quickfile/Makefile +++ b/quickfile/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=quickfile -PKG_VERSION:=1.0.16 -PKG_RELEASE:=1 +PKG_VERSION:=1.0.17 +PKG_RELEASE:=2 PKG_SOURCE:=quickfile-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://r2.cooluc.com/source