From 00106d0a89e665fe30de2301a7e1ffd40ed5bebe Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Sat, 23 May 2026 08:41:38 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=90=B6=20Sync=202026-05-23=2008:41:38?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fan2go/Makefile | 4 +- kai/Makefile | 4 +- kai_session/Makefile | 4 +- luci-app-kai/Makefile | 4 +- luci-app-passwall2/Makefile | 22 +-- .../luasrc/controller/passwall2.lua | 18 +++ .../model/cbi/passwall2/client/acl_config.lua | 99 +----------- .../cbi/passwall2/client/node_config.lua | 2 + .../cbi/passwall2/client/node_subscribe.lua | 5 - .../client/node_subscribe_config.lua | 22 ++- .../model/cbi/passwall2/client/type/ray.lua | 13 +- .../cbi/passwall2/client/type/sing-box.lua | 10 +- .../model/cbi/passwall2/client/type/ss.lua | 62 -------- .../model/cbi/passwall2/client/type/tuic.lua | 145 ------------------ .../cbi/passwall2/server/type/hysteria2.lua | 15 +- .../model/cbi/passwall2/server/type/ray.lua | 25 +-- .../cbi/passwall2/server/type/sing-box.lua | 44 +++--- .../cbi/passwall2/server/type/ss-rust.lua | 14 +- .../model/cbi/passwall2/server/type/ss.lua | 78 ---------- .../model/cbi/passwall2/server/type/ssr.lua | 14 +- .../model/cbi/passwall2/server/user.lua | 24 ++- luci-app-passwall2/luasrc/passwall2/api.lua | 89 +++++++++++ .../luasrc/passwall2/server_app.lua | 2 +- .../luasrc/passwall2/util_shadowsocks.lua | 6 +- .../luasrc/passwall2/util_tuic.lua | 68 -------- .../luasrc/passwall2/util_xray.lua | 5 + .../view/passwall2/node_config/footer.htm | 4 +- .../view/passwall2/node_config/header.htm | 2 +- .../passwall2/node_config/link_share_man.htm | 18 +-- .../view/passwall2/server/config_footer.htm | 27 ++++ .../view/passwall2/server/config_header.htm | 56 +++++++ luci-app-passwall2/po/fa/passwall2.po | 39 ----- luci-app-passwall2/po/ru/passwall2.po | 39 ----- luci-app-passwall2/po/zh-cn/passwall2.po | 39 ----- luci-app-passwall2/po/zh-tw/passwall2.po | 39 ----- .../root/usr/share/passwall2/app.sh | 20 --- .../root/usr/share/passwall2/subscribe.lua | 43 +++--- 37 files changed, 353 insertions(+), 771 deletions(-) delete mode 100644 luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ss.lua delete mode 100644 luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/tuic.lua delete mode 100644 luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss.lua delete mode 100644 luci-app-passwall2/luasrc/passwall2/util_tuic.lua create mode 100644 luci-app-passwall2/luasrc/view/passwall2/server/config_footer.htm create mode 100644 luci-app-passwall2/luasrc/view/passwall2/server/config_header.htm diff --git a/fan2go/Makefile b/fan2go/Makefile index 8c8734e9..f40c0248 100644 --- a/fan2go/Makefile +++ b/fan2go/Makefile @@ -1,8 +1,8 @@ include $(TOPDIR)/rules.mk PKG_NAME:=fan2go -PKG_VERSION:=0.13.0 -PKG_RELEASE:=1 +PKG_VERSION:=0.14.0 +PKG_RELEASE:=2 PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://codeload.github.com/markusressel/fan2go/tar.gz/$(PKG_VERSION)? diff --git a/kai/Makefile b/kai/Makefile index caa4ced0..96eecf73 100644 --- a/kai/Makefile +++ b/kai/Makefile @@ -10,8 +10,8 @@ include $(TOPDIR)/rules.mk PKG_ARCH_kai:=$(ARCH) PKG_NAME:=kai -PKG_VERSION:=0.0.5 -PKG_RELEASE:=4 +PKG_VERSION:=0.0.6 +PKG_RELEASE:=5 PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/linkease/istore-packages/releases/download/prebuilt/ PKG_HASH:=skip diff --git a/kai_session/Makefile b/kai_session/Makefile index dcf0d79a..523f16c3 100644 --- a/kai_session/Makefile +++ b/kai_session/Makefile @@ -10,8 +10,8 @@ include $(TOPDIR)/rules.mk PKG_ARCH_kai_session:=$(ARCH) PKG_NAME:=kai_session -PKG_VERSION:=0.0.5 -PKG_RELEASE:=4 +PKG_VERSION:=0.0.6 +PKG_RELEASE:=5 PKG_SOURCE:=$(PKG_NAME)-binary-$(PKG_VERSION).tar.gz PKG_SOURCE_URL:=https://github.com/linkease/istore-packages/releases/download/prebuilt/ PKG_HASH:=skip diff --git a/luci-app-kai/Makefile b/luci-app-kai/Makefile index 10151863..ac464572 100755 --- a/luci-app-kai/Makefile +++ b/luci-app-kai/Makefile @@ -7,8 +7,8 @@ include $(TOPDIR)/rules.mk LUCI_TITLE:=kai -PKG_VERSION:=1.0.1 -PKG_RELEASE:=7 +PKG_VERSION:=1.0.2 +PKG_RELEASE:=8 LUCI_DEPENDS:=+kai +kai_session +luci-compat LUCI_MINIFY_CSS:=0 LUCI_MINIFY_JS:=0 diff --git a/luci-app-passwall2/Makefile b/luci-app-passwall2/Makefile index cf4b012f..da6ed0d1 100644 --- a/luci-app-passwall2/Makefile +++ b/luci-app-passwall2/Makefile @@ -7,7 +7,7 @@ include $(TOPDIR)/rules.mk PKG_NAME:=luci-app-passwall2 PKG_VERSION:=26.5.19 -PKG_RELEASE:=46 +PKG_RELEASE:=47 PKG_PO_VERSION:=$(PKG_VERSION) PKG_CONFIG_DEPENDS:= \ @@ -16,14 +16,11 @@ PKG_CONFIG_DEPENDS:= \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Haproxy \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Hysteria \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy \ - CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client \ - CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Server \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Client \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_ShadowsocksR_Libev_Server \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs \ - CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client \ CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin LUCI_TITLE:=LuCI support for PassWall 2 @@ -119,17 +116,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_NaiveProxy select PACKAGE_naiveproxy default n -config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Client - bool "Include Shadowsocks Libev Client" - select PACKAGE_shadowsocks-libev-ss-local - select PACKAGE_shadowsocks-libev-ss-redir - default y - -config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Libev_Server - bool "Include Shadowsocks Libev Server" - select PACKAGE_shadowsocks-libev-ss-server - default n - config PACKAGE_$(PKG_NAME)_INCLUDE_Shadowsocks_Rust_Client bool "Include Shadowsocks Rust Client" depends on !i386 @@ -158,12 +144,6 @@ config PACKAGE_$(PKG_NAME)_INCLUDE_Simple_Obfs select PACKAGE_simple-obfs-client default y -config PACKAGE_$(PKG_NAME)_INCLUDE_tuic_client - bool "Include tuic-client" - depends on aarch64||arm||i386||x86_64 - select PACKAGE_tuic-client - default n - config PACKAGE_$(PKG_NAME)_INCLUDE_V2ray_Plugin bool "Include V2ray-Plugin (Shadowsocks Plugin)" select PACKAGE_v2ray-plugin diff --git a/luci-app-passwall2/luasrc/controller/passwall2.lua b/luci-app-passwall2/luasrc/controller/passwall2.lua index 480d1d33..26a45907 100644 --- a/luci-app-passwall2/luasrc/controller/passwall2.lua +++ b/luci-app-passwall2/luasrc/controller/passwall2.lua @@ -59,6 +59,7 @@ function index() entry({"admin", "services", appname, "server_user"}, cbi(appname .. "/server/user")).leaf = true --[[ API ]] + entry({"admin", "services", appname, "server_user_update"}, call("server_user_update")).leaf = true entry({"admin", "services", appname, "server_user_status"}, call("server_user_status")).leaf = true entry({"admin", "services", appname, "server_user_log"}, call("server_user_log")).leaf = true entry({"admin", "services", appname, "server_get_log"}, call("server_get_log")).leaf = true @@ -685,6 +686,23 @@ function rollback_rules() http_write_json_ok() end +function server_user_update() + local id = http.formvalue("id") -- Node id + local data = http.formvalue("data") -- json new Data + if id and data then + local data_t = jsonParse(data) or {} + if next(data_t) then + for k, v in pairs(data_t) do + uci:set(appname .. "_server", id, k, v) + end + api.uci_save(uci, appname .. "_server") + http_write_json_ok() + return + end + end + http_write_json_error() +end + function server_user_status() local e = {} e.index = http.formvalue("index") diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua index 6f7b1866..b8b77501 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/acl_config.lua @@ -78,103 +78,10 @@ o.rmempty = false o = s:option(Value, "interface", translate("Source Interface")) o:value("", translate("All")) --- Populate with actual kernel network devices instead of UCI interface names, --- because the backend (nftables iifname / iptables -i) matches kernel device names. -do - local nfs = require "nixio.fs" - local _cursor = require("luci.model.uci").cursor() - local _sysnet = "/sys/class/net/" - - -- Map UCI interface names to their device names and vice versa - local _iface_to_dev = {} - local _dev_to_ifaces = {} - local _iface_proto = {} - _cursor:foreach("network", "interface", function(sec) - local name = sec[".name"] - if name ~= "loopback" then - _iface_proto[name] = sec.proto - if sec.device then - _iface_to_dev[name] = sec.device - _dev_to_ifaces[sec.device] = _dev_to_ifaces[sec.device] or {} - table.insert(_dev_to_ifaces[sec.device], name) - end - end - end) - - -- Classify device type using sysfs attributes - local function classify_sysfs(dev) - if nfs.stat(_sysnet .. dev .. "/bridge", "type") == "dir" then - return translate("Bridge") - elseif nfs.stat(_sysnet .. dev .. "/wireless", "type") == "dir" then - return translate("Wireless Adapter") - elseif dev:match("^tun") or dev:match("^tap") or dev:match("^wg") or dev:match("^ppp") then - return translate("Tunnel Interface") - else - return translate("Ethernet Adapter") - end - end - - -- Classify offline UCI interfaces by config hints - local function classify_uci(dev_name, proto) - if dev_name and dev_name:match("^br%-") then - return translate("Bridge") - elseif proto == "wireguard" or proto == "pppoe" or proto == "pptp" or proto == "l2tp" then - return translate("Tunnel Interface") - else - return translate("Interface") - end - end - - local _seen = {} - local _devices = {} - - -- Active kernel devices from /sys/class/net/. - -- Skip bridge member ports (/master) and DSA master devices (/dsa) because - -- nftables iifname matches the parent bridge for routed traffic, not - -- individual member ports. Also skip internal virtual devices. - local _iter = nfs.dir(_sysnet) - if _iter then - for dev in _iter do - if dev ~= "lo" - and not dev:match("^veth") - and not dev:match("^ifb") - and not dev:match("^gre") - and not dev:match("^sit") - and not dev:match("^ip6tnl") - and not dev:match("^erspan") - and not nfs.stat(_sysnet .. dev .. "/master", "type") - and not nfs.stat(_sysnet .. dev .. "/dsa", "type") - then - local dtype = classify_sysfs(dev) - local label = dtype .. ': "' .. dev .. '"' - if _dev_to_ifaces[dev] then - label = label .. " (" .. table.concat(_dev_to_ifaces[dev], ", ") .. ")" - end - _devices[#_devices + 1] = { name = dev, label = label, sort = dtype .. ":" .. dev } - _seen[dev] = true - end - end - end - - -- UCI interfaces whose device does not currently exist (down tunnels, VPNs, etc.). - -- Stored by UCI name since the kernel device is not available yet. - -- Dedup by device: if two interfaces share a device, only one is shown. - for iface, dev in pairs(_iface_to_dev) do - if not _seen[dev] then - local dtype = classify_uci(dev, _iface_proto[iface]) - local label = dtype .. ': "' .. iface .. '"' - -- Sort offline entries after active devices - _devices[#_devices + 1] = { name = iface, label = label, sort = "zzz:" .. iface } - _seen[dev] = true - end - end - - table.sort(_devices, function(a, b) return a.sort < b.sort end) - for _, d in ipairs(_devices) do - o:value(d.name, d.label) - end +local iface = api.get_network_devices() +for _, d in ipairs(iface) do + o:value(d.name, d.label) end - o.validate = function(self, value, section) if value == "" or value:match("^[a-zA-Z0-9][a-zA-Z0-9%.%_%-]*$") then return value diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua index 28e3aa7d..5051bd7b 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_config.lua @@ -14,6 +14,7 @@ formvalue_key = "cbid." .. appname .. "." .. arg[1] .. "." local header = Template(appname .. "/node_config/header") header.api = api +header.config = m.config header.section = arg[1] m:append(header) @@ -91,6 +92,7 @@ end local footer = Template(appname .. "/node_config/footer") footer.api = api +footer.config = m.config footer.section = arg[1] m:append(footer) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua index a13e46ee..7140ac5c 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe.lua @@ -1,7 +1,6 @@ local api = require "luci.passwall2.api" local appname = api.appname local uci = api.uci -local has_ss = api.is_finded("ss-redir") local has_ss_rust = api.is_finded("sslocal") local has_singbox = api.finded_com("sing-box") local has_xray = api.finded_com("xray") @@ -12,10 +11,6 @@ local vmess_type = {} local vless_type = {} local hysteria2_type = {} local xray_version = api.get_app_version("xray") -if has_ss then - local s = "shadowsocks-libev" - table.insert(ss_type, s) -end if has_ss_rust then local s = "shadowsocks-rust" table.insert(ss_type, s) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua index 6be6bacf..1cc68769 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/node_subscribe_config.lua @@ -15,7 +15,6 @@ end m:append(Template(appname .. "/cbi/nodes_listvalue_com")) -local has_ss = api.is_finded("ss-redir") local has_ss_rust = api.is_finded("sslocal") local has_singbox = api.finded_com("sing-box") local has_xray = api.finded_com("xray") @@ -26,10 +25,6 @@ local vmess_type = {} local vless_type = {} local hysteria2_type = {} local xray_version = api.get_app_version("xray") -if has_ss then - local s = "shadowsocks-libev" - table.insert(ss_type, s) -end if has_ss_rust then local s = "shadowsocks-rust" table.insert(ss_type, s) @@ -223,6 +218,14 @@ if #hysteria2_type > 0 then for key, value in pairs(hysteria2_type) do o:value(value) end + + o = s:option(Value, "hysteria_up_mbps", "Hy/Hy2 " .. translate("Max upload Mbps")) + o.datatype = "uinteger" + o.default = "100" + + o = s:option(Value, "hysteria_down_mbps", "Hy/Hy2 " .. translate("Max download Mbps")) + o.datatype = "uinteger" + o.default = "100" end o = s:option(Flag, "boot_update", translate("Update Once on Boot"), translate("Updates the subscription the first time runs automatically after each system boot.")) @@ -287,6 +290,7 @@ o = s:option(ListValue, "chain_proxy", translate("Chain Proxy")) o:value("", translate("Close(Not use)")) o:value("1", translate("Preproxy Node")) o:value("2", translate("Landing Node")) +o:value("3", translate("Outbound Interface")) local descrStr = "Chained proxy works only with Xray or Sing-box nodes.
" descrStr = descrStr .. "You can only use manual or imported nodes as chained nodes." @@ -304,6 +308,14 @@ o2.description = descrStr o2.template = appname .. "/cbi/nodes_listvalue" o2.group = {} +o3 = s:option(Value, "outbound_iface", translate("Outbound Interface")) +o3:depends({ ["chain_proxy"] = "3" }) +o3:value("", translate("All")) +local iface = api.get_network_devices() +for _, d in ipairs(iface) do + o3:value(d.name, d.label) +end + for k, v in pairs(nodes_table) do if (v.type == "Xray" or v.type == "sing-box") and (not v.chain_proxy or v.chain_proxy == "") and v.add_mode ~= "2" then o1:value(v.id, v.remark) 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 012f4952..f1264f1f 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 @@ -78,6 +78,7 @@ if not arg_select_proto:find("_") then load_normal_options = true end +local netdev_list = api.get_network_devices() local node_list = api.get_node_list() local fallback_list = {} local is_balancer = nil @@ -270,8 +271,10 @@ end -- [[ Load balancing End ]] if load_iface_options then -- [[ Custom Interface Start ]] o = s:option(Value, _n("iface"), translate("Interface")) - o.default = "eth1" o:depends({ [_n("protocol")] = "_iface" }) + for _, d in ipairs(netdev_list) do + o:value(d.name, d.label) + end end -- [[ Custom Interface End ]] @@ -793,6 +796,7 @@ if not load_shunt_options then if not (load_iface_options or load_balancing_options) then -- Special node cannot be use pre-proxy. o:value("1", translate("Preproxy Node")) + o:value("3", translate("Outbound Interface")) end o:value("2", translate("Landing Node")) @@ -801,6 +805,13 @@ if not load_shunt_options then o1.template = appname .. "/cbi/nodes_listvalue" o1.group = {} + o3 = s:option(Value, _n("outbound_iface"), translate("Outbound Interface")) + o3:depends({ [_n("chain_proxy")] = "3" }) + o3:value("", translate("All")) + for _, d in ipairs(netdev_list) do + o3:value(d.name, d.label) + 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.template = appname .. "/cbi/nodes_listvalue" 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 cfb5fb61..a3c591ca 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 @@ -94,6 +94,7 @@ if not arg_select_proto:find("_") then load_normal_options = true end +local netdev_list = api.get_network_devices() local node_list = api.get_node_list() if load_urltest_options then -- [[ URLTest Start ]] @@ -198,8 +199,10 @@ end -- [[ URLTest End ]] if load_iface_options then -- [[ Custom Interface Start ]] o = s:option(Value, _n("iface"), translate("Interface")) - o.default = "eth1" o:depends({ [_n("protocol")] = "_iface" }) + for _, d in ipairs(netdev_list) do + o:value(d.name, d.label) + end end -- [[ Custom Interface End ]] @@ -875,8 +878,11 @@ if not load_shunt_options then o1.group = {} o3 = s:option(Value, _n("outbound_iface"), translate("Outbound Interface")) - o3.default = "eth1" o3:depends({ [_n("chain_proxy")] = "3" }) + o3:value("", translate("All")) + for _, d in ipairs(netdev_list) do + o3:value(d.name, d.label) + end o2 = s:option(ListValue, _n("to_node"), translate("Landing Node"), translate("Only support a layer of proxy.")) o2:depends({ [_n("chain_proxy")] = "2", [_n("hysteria2_realms")] = false }) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ss.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ss.lua deleted file mode 100644 index b1abf4a5..00000000 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/ss.lua +++ /dev/null @@ -1,62 +0,0 @@ -local m, s = ... - -if not api.is_finded("ss-local") then - return -end - -type_name = "SS" - --- [[ Shadowsocks Libev ]] - -s.fields["type"]:value(type_name, "Shadowsocks Libev") - -if s.val["type"] ~= type_name then - return -end - -local option_prefix = "ss_" - -local function _n(name) - return option_prefix .. name -end - -local ss_encrypt_method_list = { - "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", - "aes-192-ctr", "aes-256-ctr", "bf-cfb", "salsa20", "chacha20", "chacha20-ietf", - "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305" -} - -o = s:option(Value, _n("address"), translate("Address (Support Domain Name)")) - -o = s:option(Value, _n("port"), translate("Port")) -o.datatype = "port" - -o = s:option(Value, _n("password"), translate("Password")) -o.password = true - -o = s:option(Value, _n("method"), translate("Encrypt Method")) -for a, t in ipairs(ss_encrypt_method_list) do o:value(t) end - -o = s:option(Value, _n("timeout"), translate("Connection Timeout")) -o.datatype = "uinteger" -o.default = 300 - -o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open"), translate("Need node support required")) -o.default = 0 - -o = s:option(Flag, _n("plugin_enabled"), translate("plugin")) -o.default = 0 - -o = s:option(ListValue, _n("plugin"), "SIP003 " .. translate("plugin")) -o.default = "none" -o:value("none", translate("none")) -if api.is_finded("xray-plugin") then o:value("xray-plugin") end -if api.is_finded("v2ray-plugin") then o:value("v2ray-plugin") end -if api.is_finded("obfs-local") then o:value("obfs-local") end -o:depends({ [_n("plugin_enabled")] = true }) - -o = s:option(Value, _n("plugin_opts"), translate("opts")) -o:depends({ [_n("plugin_enabled")] = true }) - -api.luci_types(arg[1], m, s, type_name, option_prefix) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/tuic.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/tuic.lua deleted file mode 100644 index fb7f91ac..00000000 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/client/type/tuic.lua +++ /dev/null @@ -1,145 +0,0 @@ -local m, s = ... - -if not api.is_finded("tuic-client") then - return -end - -type_name = "TUIC" - --- [[ TUIC ]] - -s.fields["type"]:value(type_name, "TUIC") - -if s.val["type"] ~= type_name then - return -end - -local option_prefix = "tuic_" - -local function _n(name) - return option_prefix .. name -end - -o = s:option(Value, _n("address"), translate("Address (Support Domain Name)")) - -o = s:option(Value, _n("port"), translate("Port")) -o.datatype = "port" - -o = s:option(Value, _n("uuid"), translate("ID")) -o.password = true - --- Tuic Password for remote server connect -o = s:option(Value, _n("password"), translate("TUIC User Password For Connect Remote Server")) -o.password = true -o.rmempty = true -o.default = "" -o.rewrite_option = o.option - ---[[ --- Tuic username for local socks connect -o = s:option(Value, _n("socks_username"), translate("TUIC UserName For Local Socks")) -o.rmempty = true -o.default = "" -o.rewrite_option = o.option - --- Tuic Password for local socks connect -o = s:option(Value, _n("socks_password"), translate("TUIC Password For Local Socks")) -o.password = true -o.rmempty = true -o.default = "" -o.rewrite_option = o.option ---]] - -o = s:option(Value, _n("ip"), translate("Set the TUIC proxy server ip address")) -o.datatype = "ipaddr" -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(ListValue, _n("udp_relay_mode"), translate("UDP relay mode")) -o:value("native", translate("native")) -o:value("quic", translate("QUIC")) -o.default = "native" -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(ListValue, _n("congestion_control"), translate("Congestion control algorithm")) -o:value("bbr", translate("BBR")) -o:value("cubic", translate("CUBIC")) -o:value("new_reno", translate("New Reno")) -o.default = "cubic" -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(Value, _n("heartbeat"), translate("Heartbeat interval(second)")) -o.datatype = "uinteger" -o.default = "3" -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(Value, _n("timeout"), translate("Timeout for establishing a connection to server(second)")) -o.datatype = "uinteger" -o.default = "8" -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(Value, _n("gc_interval"), translate("Garbage collection interval(second)")) -o.datatype = "uinteger" -o.default = "3" -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(Value, _n("gc_lifetime"), translate("Garbage collection lifetime(second)")) -o.datatype = "uinteger" -o.default = "15" -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(Value, _n("send_window"), translate("TUIC send window")) -o.datatype = "uinteger" -o.default = 20971520 -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(Value, _n("receive_window"), translate("TUIC receive window")) -o.datatype = "uinteger" -o.default = 10485760 -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(Value, _n("max_package_size"), translate("TUIC Maximum packet size the socks5 server can receive from external, in bytes")) -o.datatype = "uinteger" -o.default = 1500 -o.rmempty = true -o.rewrite_option = o.option - ---Tuic settings for the local inbound socks5 server -o = s:option(Flag, _n("dual_stack"), translate("Set if the listening socket should be dual-stack")) -o.default = 0 -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(Flag, _n("disable_sni"), translate("Disable SNI")) -o.default = 0 -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(Flag, _n("zero_rtt_handshake"), translate("Enable 0-RTT QUIC handshake")) -o.default = 0 -o.rmempty = true -o.rewrite_option = o.option - -o = s:option(ListValue, _n("tls_alpn"), translate("TLS ALPN")) -o.rmempty = true -o.default = "" -o:value("", translate("Default")) -o:value("h3") -o:value("h2") -o:value("h3,h2") -o:value("http/1.1") -o:value("h2,http/1.1") -o:value("h3,h2,http/1.1") -o:value("spdy/3.1") -o:value("h3,spdy/3.1") -o.rewrite_option = o.option - -api.luci_types(arg[1], m, s, type_name, option_prefix) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/hysteria2.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/hysteria2.lua index 74f5a37d..89742db8 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/hysteria2.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/hysteria2.lua @@ -1,28 +1,29 @@ local m, s = ... -local api = require "luci.passwall2.api" - if not api.finded_com("hysteria") then return end local type_name = "Hysteria2" +-- [[ Hysteria2 ]] + +s.fields["type"]:value(type_name, "Hysteria2") + +if s.val["type"] and s.val["type"] ~= type_name then + return +end + local option_prefix = "hysteria2_" local function _n(name) return option_prefix .. name end --- [[ Hysteria2 ]] - -s.fields["type"]:value(type_name, "Hysteria2") - o = s:option(Flag, _n("custom"), translate("Use Custom Config")) o = s:option(Value, _n("port"), translate("Listen Port")) o.datatype = "port" -o.rmempty = false o:depends({ [_n("custom")] = false }) o = s:option(Flag, _n("realms"), translate("Realms")) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua index 3a4d9ba3..ff99b15b 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ray.lua @@ -1,13 +1,22 @@ local m, s = ... -local api = require "luci.passwall2.api" - if not api.finded_com("xray") then return end local type_name = "Xray" +-- [[ Xray ]] + +s.fields["type"]:value(type_name, "Xray") +if not s.fields["type"].default then + s.fields["type"].default = type_name +end + +if s.val["type"] and s.val["type"] ~= type_name then + return +end + local option_prefix = "xray_" local function _n(name) @@ -22,13 +31,6 @@ local header_type_list = { "none", "srtp", "utp", "wechat-video", "dtls", "wireguard", "dns" } --- [[ Xray ]] - -s.fields["type"]:value(type_name, "Xray") -if not s.fields["type"].default then - s.fields["type"].default = type_name -end - o = s:option(Flag, _n("custom"), translate("Use Custom Config")) o = s:option(ListValue, _n("protocol"), translate("Protocol")) @@ -487,8 +489,11 @@ o:depends({ [_n("outbound_node")] = "_socks"}) o:depends({ [_n("outbound_node")] = "_http"}) o = s:option(Value, _n("outbound_node_iface"), translate("Interface")) -o.default = "eth1" o:depends({ [_n("outbound_node")] = "_iface"}) +local netdev_list = api.get_network_devices() +for _, d in ipairs(netdev_list) do + o:value(d.name, d.label) +end o = s:option(TextValue, _n("custom_config"), translate("Custom Config")) o.rows = 10 diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua index 96beede8..dd3cb2f4 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/sing-box.lua @@ -1,30 +1,13 @@ local m, s = ... -local api = require "luci.passwall2.api" - local singbox_bin = api.finded_com("sing-box") if not singbox_bin then return end -local fs = api.fs - -local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'") - local type_name = "sing-box" -local option_prefix = "singbox_" - -local function _n(name) - return option_prefix .. name -end - -local ss_method_list = { - "none", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", - "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" -} - -- [[ Sing-Box ]] s.fields["type"]:value(type_name, "Sing-Box") @@ -32,6 +15,23 @@ if not s.fields["type"].default then s.fields["type"].default = type_name end +if s.val["type"] and s.val["type"] ~= type_name then + return +end + +local option_prefix = "singbox_" + +local function _n(name) + return option_prefix .. name +end + +local singbox_tags = luci.sys.exec(singbox_bin .. " version | grep 'Tags:' | awk '{print $2}'") + +local ss_method_list = { + "none", "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", "xchacha20-ietf-poly1305", + "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" +} + o = s:option(Flag, _n("custom"), translate("Use Custom Config")) o = s:option(ListValue, _n("protocol"), translate("Protocol")) @@ -58,7 +58,6 @@ o:depends({ [_n("custom")] = false }) o = s:option(Value, _n("port"), translate("Listen Port")) o.datatype = "port" -o.rmempty = false o:depends({ [_n("custom")] = false }) o = s:option(Flag, _n("auth"), translate("Auth")) @@ -302,7 +301,7 @@ o:depends({ [_n("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "hysteria2" }) o.validate = function(self, value, t) if value and value ~= "" then - if not nixio.fs.access(value) then + if not fs.access(value) then return nil, translate("Can't find this file!") else return value @@ -321,7 +320,7 @@ o:depends({ [_n("protocol")] = "tuic" }) o:depends({ [_n("protocol")] = "hysteria2" }) o.validate = function(self, value, t) if value and value ~= "" then - if not nixio.fs.access(value) then + if not fs.access(value) then return nil, translate("Can't find this file!") else return value @@ -464,8 +463,11 @@ o:depends({ [_n("outbound_node")] = "_socks" }) o:depends({ [_n("outbound_node")] = "_http" }) o = s:option(Value, _n("outbound_node_iface"), translate("Interface")) -o.default = "eth1" o:depends({ [_n("outbound_node")] = "_iface" }) +local netdev_list = api.get_network_devices() +for _, d in ipairs(netdev_list) do + o:value(d.name, d.label) +end o = s:option(TextValue, _n("custom_config"), translate("Custom Config")) o.rows = 10 diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss-rust.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss-rust.lua index 2b800be2..d0939430 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss-rust.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss-rust.lua @@ -1,13 +1,19 @@ local m, s = ... -local api = require "luci.passwall2.api" - if not api.is_finded("ssserver") then return end local type_name = "SS-Rust" +-- [[ Shadowsocks Rust ]] + +s.fields["type"]:value(type_name, translate("Shadowsocks Rust")) + +if s.val["type"] and s.val["type"] ~= type_name then + return +end + local option_prefix = "ssrust_" local function _n(name) @@ -20,10 +26,6 @@ local ssrust_encrypt_method_list = { "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha8-poly1305", "2022-blake3-chacha20-poly1305" } --- [[ Shadowsocks Rust ]] - -s.fields["type"]:value(type_name, translate("Shadowsocks Rust")) - o = s:option(Flag, _n("custom"), translate("Use Custom Config")) o = s:option(Value, _n("port"), translate("Listen Port")) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss.lua deleted file mode 100644 index 093ab70c..00000000 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ss.lua +++ /dev/null @@ -1,78 +0,0 @@ -local m, s = ... - -local api = require "luci.passwall2.api" - -if not api.is_finded("ss-server") then - return -end - -local type_name = "SS" - -local option_prefix = "ss_" - -local function _n(name) - return option_prefix .. name -end - -local ss_encrypt_method_list = { - "rc4-md5", "aes-128-cfb", "aes-192-cfb", "aes-256-cfb", "aes-128-ctr", - "aes-192-ctr", "aes-256-ctr", "bf-cfb", "camellia-128-cfb", - "camellia-192-cfb", "camellia-256-cfb", "salsa20", "chacha20", - "chacha20-ietf", -- aead - "aes-128-gcm", "aes-192-gcm", "aes-256-gcm", "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305" -} - --- [[ Shadowsocks ]] - -s.fields["type"]:value(type_name, translate("Shadowsocks")) - -o = s:option(Flag, _n("custom"), translate("Use Custom Config")) - -o = s:option(Value, _n("port"), translate("Listen Port")) -o.datatype = "port" -o:depends({ [_n("custom")] = false }) - -o = s:option(Value, _n("password"), translate("Password")) -o.password = true -o:depends({ [_n("custom")] = false }) - -o = s:option(ListValue, _n("method"), translate("Encrypt Method")) -for a, t in ipairs(ss_encrypt_method_list) do o:value(t) end -o:depends({ [_n("custom")] = false }) - -o = s:option(Value, _n("timeout"), translate("Connection Timeout")) -o.datatype = "uinteger" -o.default = 300 -o:depends({ [_n("custom")] = false }) - -o = s:option(Flag, _n("tcp_fast_open"), "TCP " .. translate("Fast Open")) -o.default = "0" -o:depends({ [_n("custom")] = false }) - -o = s:option(TextValue, _n("custom_config"), translate("Custom Config")) -o.rows = 10 -o.wrap = "off" -o:depends({ [_n("custom")] = true }) -o.validate = function(self, value, t) - if value and api.jsonc.parse(value) then - return value - else - return nil, translate("Custom Config") .. " " .. translate("Must be JSON text!") - end -end -o.custom_cfgvalue = function(self, section, value) - local config_str = m:get(section, "config_str") - if config_str then - return api.base64Decode(config_str) - end -end -o.custom_write = function(self, section, value) - m:set(section, "config_str", api.base64Encode(value) or "") -end - -o = s:option(Flag, _n("log"), translate("Log")) -o.default = "1" -o.rmempty = false - -api.luci_types(arg[1], m, s, type_name, option_prefix) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ssr.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ssr.lua index 3bcf5597..02a94f61 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ssr.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/type/ssr.lua @@ -1,13 +1,19 @@ local m, s = ... -local api = require "luci.passwall2.api" - if not api.is_finded("ssr-server") then return end local type_name = "SSR" +-- [[ ShadowsocksR ]] + +s.fields["type"]:value(type_name, translate("ShadowsocksR")) + +if s.val["type"] and s.val["type"] ~= type_name then + return +end + local option_prefix = "ssr_" local function _n(name) @@ -33,10 +39,6 @@ local ssr_obfs_list = { "tls1.0_session_auth", "tls1.2_ticket_auth" } --- [[ ShadowsocksR ]] - -s.fields["type"]:value(type_name, translate("ShadowsocksR")) - o = s:option(Flag, _n("custom"), translate("Use Custom Config")) o = s:option(Value, _n("port"), translate("Listen Port")) diff --git a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua index a5dc64a9..c50d5ca9 100644 --- a/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua +++ b/luci-app-passwall2/luasrc/model/cbi/passwall2/server/user.lua @@ -1,7 +1,6 @@ -local api = require "luci.passwall2.api" -local appname = api.appname -local fs = api.fs -local types_dir = "/usr/lib/lua/luci/model/cbi/" .. appname .. "/server/type/" +api = require "luci.passwall2.api" +appname = api.appname +fs = api.fs m = Map("passwall2_server", translate("Server Config")) m.redirect = api.url("server") @@ -11,12 +10,21 @@ if not arg[1] or not m:get(arg[1]) then luci.http.redirect(m.redirect) end +local header = Template(appname .. "/server/config_header") +header.api = api +header.config = m.config +header.section = arg[1] +m:append(header) + m:append(Template(appname .. "/cbi/nodes_listvalue_com")) s = m:section(NamedSection, arg[1], "user", "") s.addremove = false s.dynamic = false +local types_dir = "/usr/lib/lua/luci/model/cbi/" .. appname .. "/server/type/" +s.val = m:get(arg[1]) or {} + o = s:option(Flag, "enable", translate("Enable")) o.default = "1" o.rmempty = false @@ -32,8 +40,6 @@ for filename in fs.dir(types_dir) do table.insert(type_table, filename) end table.sort(type_table, function(a, b) - if a == "socks.lua" then return true end - if b == "socks.lua" then return false end return a < b end) @@ -42,4 +48,10 @@ for index, value in ipairs(type_table) do setfenv(p_func, getfenv(1))(m, s) end +local footer = Template(appname .. "/server/config_footer") +footer.api = api +footer.config = m.config +footer.section = arg[1] +m:append(footer) + return m diff --git a/luci-app-passwall2/luasrc/passwall2/api.lua b/luci-app-passwall2/luasrc/passwall2/api.lua index 71a59821..e2510f51 100644 --- a/luci-app-passwall2/luasrc/passwall2/api.lua +++ b/luci-app-passwall2/luasrc/passwall2/api.lua @@ -1367,6 +1367,11 @@ function set_apply_on_parse(map) end function luci_types(id, m, s, type_name, option_prefix) + local fv_type + local field_type = s.fields["type"] + if field_type then + fv_type = field_type:formvalue(id) + end local rewrite_option_table = {} for key, value in pairs(s.fields) do if key:find(option_prefix) == 1 then @@ -1435,6 +1440,10 @@ function luci_types(id, m, s, type_name, option_prefix) else s.fields[key]:depends({ type = type_name }) end + + if fv_type and fv_type ~= type_name then + s.fields[key].rmempty = true + end end end end @@ -1623,3 +1632,83 @@ function parse_realm_uri(uri) end return realm end + +function get_network_devices() + local _sysnet = "/sys/class/net/" + -- Map UCI interface names to their device names and vice versa + local _iface_to_dev = {} + local _dev_to_ifaces = {} + local _iface_proto = {} + uci:foreach("network", "interface", function(sec) + local name = sec[".name"] + if name ~= "loopback" then + _iface_proto[name] = sec.proto + if sec.device then + _iface_to_dev[name] = sec.device + _dev_to_ifaces[sec.device] = _dev_to_ifaces[sec.device] or {} + table.insert(_dev_to_ifaces[sec.device], name) + end + end + end) + -- Classify device type using sysfs attributes + local function classify_sysfs(dev) + if fs.stat(_sysnet .. dev .. "/bridge", "type") == "dir" then + return i18n.translate("Bridge") + elseif fs.stat(_sysnet .. dev .. "/wireless", "type") == "dir" then + return i18n.translate("Wireless Adapter") + elseif dev:match("^tun") or dev:match("^tap") or dev:match("^wg") or dev:match("^ppp") then + return i18n.translate("Tunnel Interface") + else + return i18n.translate("Ethernet Adapter") + end + end + -- Classify offline UCI interfaces by config hints + local function classify_uci(dev_name, proto) + if dev_name and dev_name:match("^br%-") then + return i18n.translate("Bridge") + elseif proto == "wireguard" or proto == "pppoe" or proto == "pptp" or proto == "l2tp" then + return i18n.translate("Tunnel Interface") + else + return i18n.translate("Interface") + end + end + + local _seen = {} + local _devices = {} + -- Active kernel devices from /sys/class/net/ + -- Skip bridge member ports (/master) and DSA master devices (/dsa) + local _iter = fs.dir(_sysnet) + if _iter then + for dev in _iter do + if dev ~= "lo" + and not dev:match("^veth") + and not dev:match("^ifb") + and not dev:match("^gre") + and not dev:match("^sit") + and not dev:match("^ip6tnl") + and not dev:match("^erspan") + and not fs.stat(_sysnet .. dev .. "/master", "type") + and not fs.stat(_sysnet .. dev .. "/dsa", "type") + then + local dtype = classify_sysfs(dev) + local label = dtype .. ': "' .. dev .. '"' + if _dev_to_ifaces[dev] then + label = label .. " (" .. table.concat(_dev_to_ifaces[dev], ", ") .. ")" + end + _devices[#_devices + 1] = { name = dev, label = label, sort = dtype .. ":" .. dev } + _seen[dev] = true + end + end + end + -- UCI interfaces whose device does not currently exist + for iface, dev in pairs(_iface_to_dev) do + if not _seen[dev] then + local dtype = classify_uci(dev, _iface_proto[iface]) + local label = dtype .. ': "' .. iface .. '"' + _devices[#_devices + 1] = { name = iface, label = label, sort = "zzz:" .. iface } + _seen[dev] = true + end + end + table.sort(_devices, function(a, b) return a.sort < b.sort end) + return _devices +end diff --git a/luci-app-passwall2/luasrc/passwall2/server_app.lua b/luci-app-passwall2/luasrc/passwall2/server_app.lua index 6203614f..360305ff 100644 --- a/luci-app-passwall2/luasrc/passwall2/server_app.lua +++ b/luci-app-passwall2/luasrc/passwall2/server_app.lua @@ -120,7 +120,7 @@ local function start() local config_file = CONFIG_PATH .. "/" .. id .. ".json" local udp_forward = 1 local type = user.type or "" - if type == "SS" or type == "SSR" then + if type == "SSR" then if user.custom == "1" and user.config_str then config = jsonc.parse(api.base64Decode(user.config_str)) else diff --git a/luci-app-passwall2/luasrc/passwall2/util_shadowsocks.lua b/luci-app-passwall2/luasrc/passwall2/util_shadowsocks.lua index 5978991b..f4645138 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_shadowsocks.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_shadowsocks.lua @@ -75,11 +75,7 @@ function gen_config(var) reuse_port = true } - if node.type == "SS" then - config.plugin = plugin_file or nil - config.plugin_opts = (plugin_file) and node.plugin_opts or nil - config.mode = mode - elseif node.type == "SSR" then + if node.type == "SSR" then config.protocol = node.protocol config.protocol_param = node.protocol_param config.obfs = node.obfs diff --git a/luci-app-passwall2/luasrc/passwall2/util_tuic.lua b/luci-app-passwall2/luasrc/passwall2/util_tuic.lua deleted file mode 100644 index 9695c4f4..00000000 --- a/luci-app-passwall2/luasrc/passwall2/util_tuic.lua +++ /dev/null @@ -1,68 +0,0 @@ -module("luci.passwall2.util_tuic", package.seeall) -local api = require "luci.passwall2.api" -local uci = api.uci -local jsonc = api.jsonc - -function gen_config(var) - local node_id = var["node"] - if not node_id then - print("node Cannot be empty!") - return - end - local node = uci:get_all("passwall2", node_id) - local local_addr = var["local_addr"] - local local_port = var["local_port"] - local server_host = var["server_host"] or (node.address or ""):lower() - local server_port = var["server_port"] or node.port - local loglevel = var["loglevel"] or "warn" - - local tuic= { - relay = { - server = server_host .. ":" .. server_port, - ip = node.tuic_ip, - uuid = node.uuid, - password = node.tuic_password, - -- certificates = node.tuic_certificate and { node.tuic_certpath } or nil, - udp_relay_mode = node.tuic_udp_relay_mode, - congestion_control = node.tuic_congestion_control, - heartbeat = (tonumber(node.tuic_heartbeat) or 3) .. "s", - timeout = (tonumber(node.tuic_timeout) or 8) .. "s", - gc_interval = (tonumber(node.tuic_gc_interval) or 3) .. "s", - gc_lifetime = (tonumber(node.tuic_gc_lifetime) or 15) .. "s", - alpn = (node.tuic_tls_alpn and node.tuic_tls_alpn ~= "") and (function() - local alpn = {} - string.gsub(node.tuic_tls_alpn, '[^,]+', function(w) - table.insert(alpn, w) - end) - if #alpn > 0 then return alpn end - return nil - end)() or nil, - disable_sni = (node.tuic_disable_sni == "1"), - zero_rtt_handshake = (node.tuic_zero_rtt_handshake == "1"), - send_window = tonumber(node.tuic_send_window), - receive_window = tonumber(node.tuic_receive_window) - }, - ["local"] = { - server = "[::]:" .. local_port, - username = node.tuic_socks_username, - password = node.tuic_socks_password, - dual_stack = (node.tuic_dual_stack == "1") and true or false, - max_packet_size = tonumber(node.tuic_max_package_size) - }, - log_level = loglevel - } - return jsonc.stringify(tuic, 1) -end - -_G.gen_config = gen_config - -if arg[1] then - local func =_G[arg[1]] - if func then - local var = nil - if arg[2] then - var = jsonc.parse(arg[2]) - end - print(func(var)) - end -end diff --git a/luci-app-passwall2/luasrc/passwall2/util_xray.lua b/luci-app-passwall2/luasrc/passwall2/util_xray.lua index cf9fd5f6..b674e971 100644 --- a/luci-app-passwall2/luasrc/passwall2/util_xray.lua +++ b/luci-app-passwall2/luasrc/passwall2/util_xray.lua @@ -1219,6 +1219,11 @@ function gen_config(var) end end end + if node.chain_proxy == "3" and node.outbound_iface then + if outbound.streamSettings and outbound.streamSettings.sockopt then + outbound.streamSettings.sockopt.interface = node.outbound_iface + end + end return default_outTag, last_insert_outbound end diff --git a/luci-app-passwall2/luasrc/view/passwall2/node_config/footer.htm b/luci-app-passwall2/luasrc/view/passwall2/node_config/footer.htm index 2d9e3c77..feefc4dd 100644 --- a/luci-app-passwall2/luasrc/view/passwall2/node_config/footer.htm +++ b/luci-app-passwall2/luasrc/view/passwall2/node_config/footer.htm @@ -4,7 +4,7 @@ local api = self.api diff --git a/luci-app-passwall2/luasrc/view/passwall2/server/config_header.htm b/luci-app-passwall2/luasrc/view/passwall2/server/config_header.htm new file mode 100644 index 00000000..1957dec4 --- /dev/null +++ b/luci-app-passwall2/luasrc/view/passwall2/server/config_header.htm @@ -0,0 +1,56 @@ +<% +local api = self.api +-%> + diff --git a/luci-app-passwall2/po/fa/passwall2.po b/luci-app-passwall2/po/fa/passwall2.po index bd98dfe7..dfb60669 100644 --- a/luci-app-passwall2/po/fa/passwall2.po +++ b/luci-app-passwall2/po/fa/passwall2.po @@ -564,9 +564,6 @@ msgstr "اصلی" msgid "Transport Plugin" msgstr "افزونه انتقال" -msgid "Shadowsocks secondary encryption" -msgstr "رمزنگاری ثانویه Shadowsocks" - msgid "Obfs Type" msgstr "نوع مبهم‌سازی (Obfs)" @@ -1365,18 +1362,6 @@ msgstr "زمانی استفاده می‌شود که لینک گره شامل ا msgid "%s Node Use Type" msgstr "نوع استفاده گره %s" -msgid "Set the TUIC proxy server ip address" -msgstr "تنظیم آدرس IP سرور پروکسی TUIC" - -msgid "TUIC User Password For Connect Remote Server" -msgstr "رمز عبور کاربر TUIC برای اتصال به سرور راه دور" - -msgid "TUIC UserName For Local Socks" -msgstr "نام کاربری TUIC برای Socks محلی" - -msgid "TUIC Password For Local Socks" -msgstr "رمز عبور TUIC برای Socks محلی" - msgid "UDP relay mode" msgstr "حالت بازپخش UDP" @@ -1389,33 +1374,12 @@ msgstr "الگوریتم کنترل ازدحام" msgid "Heartbeat interval(second)" msgstr "بازه ضربان قلب (ثانیه)" -msgid "Timeout for establishing a connection to server(second)" -msgstr "مهلت زمانی برای برقراری اتصال به سرور (ثانیه)" - -msgid "Garbage collection interval(second)" -msgstr "بازه جمع‌آوری زباله (ثانیه)" - -msgid "Garbage collection lifetime(second)" -msgstr "طول عمر جمع‌آوری زباله (ثانیه)" - msgid "Disable SNI" msgstr "غیرفعال کردن SNI" msgid "Enable 0-RTT QUIC handshake" msgstr "فعال‌سازی دست تکان دادن 0-RTT QUIC" -msgid "TUIC send window" -msgstr "پنجره ارسال TUIC" - -msgid "TUIC receive window" -msgstr "پنجره دریافت TUIC" - -msgid "TUIC Maximum packet size the socks5 server can receive from external, in bytes" -msgstr "حداکثر اندازه بسته TUIC که سرور socks5 می‌تواند از خارج دریافت کند، به بایت" - -msgid "Set if the listening socket should be dual-stack" -msgstr "تنظیم کنید که سوکت شنونده دو پشته‌ای (dual-stack) باشد یا خیر" - msgid "
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)
dns: Disguising traffic as DNS requests." msgstr "
none: پیش‌فرض، بدون استتار، داده‌های ارسالی بسته‌های بدون مشخصه هستند.
srtp: مبدل شده به بسته SRTP، به عنوان داده تماس تصویری (مانند FaceTime) شناخته می‌شود.
utp: بسته‌های مبدل شده به uTP به عنوان داده دانلود شده bittorrent شناخته می‌شوند.
wechat-video: بسته‌های مبدل شده به تماس‌های تصویری WeChat.
dtls: مبدل شده به بسته DTLS 1.2.
wireguard: مبدل شده به بسته WireGuard. (نه واقعاً پروتکل WireGuard)
dns: پنهان کردن ترافیک به عنوان درخواست‌های DNS." @@ -2323,9 +2287,6 @@ msgstr "Xray از افزونه %s پشتیبانی نمی‌کند." msgid "Plugin options Incomplete." msgstr "گزینه‌های افزونه ناقص است." -msgid "shadowsocks-libev unsupport 2022 encryption." -msgstr "shadowsocks-libev از رمزنگاری 2022 پشتیبانی نمی‌کند." - msgid "Please replace %s to support %s transmission method." msgstr "لطفا برای پشتیبانی از روش انتقال %s، %s را جایگزین کنید." diff --git a/luci-app-passwall2/po/ru/passwall2.po b/luci-app-passwall2/po/ru/passwall2.po index 3e814ff5..cb5b8969 100644 --- a/luci-app-passwall2/po/ru/passwall2.po +++ b/luci-app-passwall2/po/ru/passwall2.po @@ -559,9 +559,6 @@ msgstr "Оригинал" msgid "Transport Plugin" msgstr "Плагин транспорта" -msgid "Shadowsocks secondary encryption" -msgstr "Дополнительное шифрование Shadowsocks" - msgid "global_padding" msgstr "Включить padding-заполнение" @@ -1366,18 +1363,6 @@ msgstr "Используется, если в ссылке на узел это msgid "%s Node Use Type" msgstr "Тип использования сервера %s" -msgid "Set the TUIC proxy server ip address" -msgstr "Указать IP-адрес сервера TUIC" - -msgid "TUIC User Password For Connect Remote Server" -msgstr "Пароль для подключения к удалённому серверу TUIC" - -msgid "TUIC UserName For Local Socks" -msgstr "Имя пользователя для локального SOCKS TUIC" - -msgid "TUIC Password For Local Socks" -msgstr "Пароль для локального SOCKS TUIC" - msgid "UDP relay mode" msgstr "Режим ретрансляции UDP" @@ -1390,33 +1375,12 @@ msgstr "Алгоритм контроля перегрузок" msgid "Heartbeat interval(second)" msgstr "Интервал heartbeat-пакетов (сек)" -msgid "Timeout for establishing a connection to server(second)" -msgstr "Тайм-аут установки соединения с сервером (сек)" - -msgid "Garbage collection interval(second)" -msgstr "Интервал очистки фрагментов UDP (сек)" - -msgid "Garbage collection lifetime(second)" -msgstr "Время жизни фрагментов UDP на сервере (сек)" - msgid "Disable SNI" msgstr "Отключить SNI" msgid "Enable 0-RTT QUIC handshake" msgstr "Включить 0-RTT рукопожатие QUIC" -msgid "TUIC send window" -msgstr "Окно отправки TUIC (макс. байт без подтверждения: по умолчанию 8 МБ × 2)" - -msgid "TUIC receive window" -msgstr "Окно приёма TUIC (макс. байт без подтверждения: по умолчанию 8 МБ)" - -msgid "TUIC Maximum packet size the socks5 server can receive from external, in bytes" -msgstr "Макс. размер пакета, который SOCKS5-сервер TUIC может принять извне (в байтах)" - -msgid "Set if the listening socket should be dual-stack" -msgstr "Включить поддержку dual-stack для слушающего сокета" - msgid "
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)
dns: Disguising traffic as DNS requests." msgstr "
none: по умолчанию, без маскировки, данные отправляются обычными пакетами.
srtp: маскировка под SRTP — трафик определяется как видеозвонок (например, FaceTime).
utp: маскировка под uTP — трафик определяется как BitTorrent.
wechat-video: маскировка под видеозвонок WeChat.
dtls: маскировка под DTLS 1.2.
wireguard: маскировка под WireGuard (не настоящий протокол WireGuard).
dns: маскировка трафика под DNS-запросы." @@ -2321,9 +2285,6 @@ msgstr "Xray не поддерживает плагин %s." msgid "Plugin options Incomplete." msgstr "Опции плагина указаны не полностью." -msgid "shadowsocks-libev unsupport 2022 encryption." -msgstr "shadowsocks-libev не поддерживает шифрование 2022." - msgid "Please replace %s to support %s transmission method." msgstr "Пожалуйста, замените %s, чтобы поддержать метод передачи %s." diff --git a/luci-app-passwall2/po/zh-cn/passwall2.po b/luci-app-passwall2/po/zh-cn/passwall2.po index 36492fcb..1010101b 100644 --- a/luci-app-passwall2/po/zh-cn/passwall2.po +++ b/luci-app-passwall2/po/zh-cn/passwall2.po @@ -556,9 +556,6 @@ msgstr "原版" msgid "Transport Plugin" msgstr "传输层插件" -msgid "Shadowsocks secondary encryption" -msgstr "Shadowsocks 二次加密" - msgid "Obfs Type" msgstr "混淆类型" @@ -1357,18 +1354,6 @@ msgstr "当节点链接未包含该参数时,将使用此设置。" msgid "%s Node Use Type" msgstr "%s 节点使用类型" -msgid "Set the TUIC proxy server ip address" -msgstr "指定远程TUIC服务器IP" - -msgid "TUIC User Password For Connect Remote Server" -msgstr "用于远程TUIC服务器连接的密码" - -msgid "TUIC UserName For Local Socks" -msgstr "用于本地Socks服务器连接的用户名" - -msgid "TUIC Password For Local Socks" -msgstr "用于本地Socks服务器连接的密码" - msgid "UDP relay mode" msgstr "UDP中继模式" @@ -1381,33 +1366,12 @@ msgstr "拥塞控制算法" msgid "Heartbeat interval(second)" msgstr "保活心跳包发送间隔(单位:秒)" -msgid "Timeout for establishing a connection to server(second)" -msgstr "连接超时时间(单位:秒)" - -msgid "Garbage collection interval(second)" -msgstr "UDP数据包片残片清理间隔(单位:秒)" - -msgid "Garbage collection lifetime(second)" -msgstr "UDP数据包残片在服务器的保留时间(单位:秒)" - msgid "Disable SNI" msgstr "关闭SNI服务器名称指示" msgid "Enable 0-RTT QUIC handshake" msgstr "客户端启用 0-RTT QUIC 连接握手" -msgid "TUIC send window" -msgstr "发送窗口(无需确认即可发送的最大字节数:默认8Mb*2)" - -msgid "TUIC receive window" -msgstr "接收窗口(无需确认即可接收的最大字节数:默认8Mb)" - -msgid "TUIC Maximum packet size the socks5 server can receive from external, in bytes" -msgstr "TUIC socks5 服务器可以从外部接收的最大数据包大小(以字节为单位)" - -msgid "Set if the listening socket should be dual-stack" -msgstr "设置监听套接字为双栈" - msgid "
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)
dns: Disguising traffic as DNS requests." msgstr "
none:默认值,不进行伪装,发送的数据是没有特征的数据包。
srtp:伪装成 SRTP 数据包,会被识别为视频通话数据(如 FaceTime)。
utp:伪装成 uTP 数据包,会被识别为 BT 下载数据。
wechat-video:伪装成微信视频通话的数据包。
dtls:伪装成 DTLS 1.2 数据包。
wireguard:伪装成 WireGuard 数据包。(并不是真正的 WireGuard 协议)
dns:把流量伪装成 DNS 请求。" @@ -2309,9 +2273,6 @@ msgstr "Xray 不支持 %s 插件。" msgid "Plugin options Incomplete." msgstr "插件选项不完整。" -msgid "shadowsocks-libev unsupport 2022 encryption." -msgstr "shadowsocks-libev 不支持2022加密。" - msgid "Please replace %s to support %s transmission method." msgstr "请更换 %s 以支持 %s 传输方式。" diff --git a/luci-app-passwall2/po/zh-tw/passwall2.po b/luci-app-passwall2/po/zh-tw/passwall2.po index ab40100e..efea133a 100644 --- a/luci-app-passwall2/po/zh-tw/passwall2.po +++ b/luci-app-passwall2/po/zh-tw/passwall2.po @@ -556,9 +556,6 @@ msgstr "原版" msgid "Transport Plugin" msgstr "傳輸層插件" -msgid "Shadowsocks secondary encryption" -msgstr "Shadowsocks 二次加密" - msgid "Obfs Type" msgstr "混淆類型" @@ -1357,18 +1354,6 @@ msgstr "當節點連結未包含該參數時,將使用此設定。" msgid "%s Node Use Type" msgstr "%s 節點使用類型" -msgid "Set the TUIC proxy server ip address" -msgstr "指定遠程TUIC服務器IP" - -msgid "TUIC User Password For Connect Remote Server" -msgstr "用於遠程TUIC服務器連接的密碼" - -msgid "TUIC UserName For Local Socks" -msgstr "用於本地Socks服務器連接的用戶名" - -msgid "TUIC Password For Local Socks" -msgstr "用於本地Socks服務器連接的密碼" - msgid "UDP relay mode" msgstr "UDP中继模式" @@ -1381,33 +1366,12 @@ msgstr "拥塞控制算法" msgid "Heartbeat interval(second)" msgstr "保活心跳包發送間隔(單位:秒)" -msgid "Timeout for establishing a connection to server(second)" -msgstr "連接超時時間(單位:秒)" - -msgid "Garbage collection interval(second)" -msgstr "UDP數据包片残片清理間隔(單位:秒)" - -msgid "Garbage collection lifetime(second)" -msgstr "UDP數据包残片在服務器的保留時間(單位:秒)" - msgid "Disable SNI" msgstr "關閉SNI服務器名称指示" msgid "Enable 0-RTT QUIC handshake" msgstr "客戶端啟用 0-RTT QUIC 連接握手" -msgid "TUIC send window" -msgstr "發送窗口(無需確認即可發送的最大字节數:默認8Mb*2)" - -msgid "TUIC receive window" -msgstr "接收窗口(無需確認即可接收的最大字节數:默認8Mb)" - -msgid "TUIC Maximum packet size the socks5 server can receive from external, in bytes" -msgstr "TUIC socks5 服務器可以从外部接收的最大數据包大小(以字节為單位)" - -msgid "Set if the listening socket should be dual-stack" -msgstr "設置監聽套接字為双栈" - msgid "
none: default, no masquerade, data sent is packets with no characteristics.
srtp: disguised as an SRTP packet, it will be recognized as video call data (such as FaceTime).
utp: packets disguised as uTP will be recognized as bittorrent downloaded data.
wechat-video: packets disguised as WeChat video calls.
dtls: disguised as DTLS 1.2 packet.
wireguard: disguised as a WireGuard packet. (not really WireGuard protocol)
dns: Disguising traffic as DNS requests." msgstr "
none:默認值,不进行伪装,發送的數据是沒有特征的數据包。
srtp:伪装成 SRTP 數据包,会被识别為視频通话數据(如 FaceTime)。
utp:伪装成 uTP 數据包,会被识别為 BT 下載數据。
wechat-video:伪装成微信視频通话的數据包。
dtls:伪装成 DTLS 1.2 數据包。
wireguard:伪装成 WireGuard 數据包。(並不是真正的 WireGuard 協議)
dns:把流量伪装成 DNS 請求。" @@ -2315,9 +2279,6 @@ msgstr "Xray 不支持 %s 插件。" msgid "Plugin options Incomplete." msgstr "插件選項不完整。" -msgid "shadowsocks-libev unsupport 2022 encryption." -msgstr "shadowsocks-libev 不支持2022加密。" - msgid "Please replace %s to support %s transmission method." msgstr "請更換 %s 以支援 %s 傳輸方式。" diff --git a/luci-app-passwall2/root/usr/share/passwall2/app.sh b/luci-app-passwall2/root/usr/share/passwall2/app.sh index 75dff526..b65a3217 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/app.sh +++ b/luci-app-passwall2/root/usr/share/passwall2/app.sh @@ -14,7 +14,6 @@ UTIL_SS=$LUA_UTIL_PATH/util_shadowsocks.lua UTIL_XRAY=$LUA_UTIL_PATH/util_xray.lua UTIL_NAIVE=$LUA_UTIL_PATH/util_naiveproxy.lua UTIL_HYSTERIA2=$LUA_UTIL_PATH/util_hysteria2.lua -UTIL_TUIC=$LUA_UTIL_PATH/util_tuic.lua SINGBOX_BIN=$(first_type $(config_t_get global_app sing_box_file) sing-box) XRAY_BIN=$(first_type $(config_t_get global_app xray_file) xray) @@ -467,18 +466,6 @@ run_socks() { lua $UTIL_SS gen_config "${_json_arg}" > $config_file [ -z "$no_run" ] && ln_run ${QUEUE_RUN} "$(first_type ssr-local)" "ssr-local" $log_file -c "$config_file" -v -u ;; - ss) - json_add_string "local_addr" "${bind}" - json_add_string "local_port" "${socks_port}" - json_add_string "mode" "tcp_and_udp" - [ -z "$no_run" ] && { - local plugin_sh="${config_file%.json}_plugin.sh" - json_add_string "plugin_sh" "${plugin_sh}" - } - local _json_arg="$(json_dump)" - lua $UTIL_SS gen_config "${_json_arg}" > $config_file - [ -z "$no_run" ] && ln_run ${QUEUE_RUN} "$(first_type ss-local)" "ss-local" $log_file -c "$config_file" -v - ;; ss-rust) json_add_string "local_socks_address" "${bind}" json_add_string "local_socks_port" "${socks_port}" @@ -509,13 +496,6 @@ run_socks() { lua $UTIL_HYSTERIA2 gen_config "${_json_arg}" > $config_file [ -z "$no_run" ] && ln_run ${QUEUE_RUN} "$(first_type $(config_t_get global_app hysteria_file))" "hysteria" $log_file -c "$config_file" client ;; - tuic) - json_add_string "local_addr" "${bind}" - json_add_string "local_port" "${socks_port}" - local _json_arg="$(json_dump)" - lua $UTIL_TUIC gen_config "${_json_arg}" > $config_file - [ -z "$no_run" ] && ln_run ${QUEUE_RUN} "$(first_type tuic-client)" "tuic-client" $log_file -c "$config_file" - ;; esac # http to socks diff --git a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua index c374fb43..35104922 100755 --- a/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua +++ b/luci-app-passwall2/root/usr/share/passwall2/subscribe.lua @@ -25,7 +25,6 @@ local log = api.log local i18n = api.i18n local lyaml = require "lyaml" -local has_ss = api.is_finded("ss-redir") local has_ss_rust = api.is_finded("sslocal") local has_ssr = api.is_finded("ssr-local") and api.is_finded("ssr-redir") local has_singbox = api.finded_com("sing-box") @@ -36,7 +35,7 @@ local DEFAULT_FILTER_KEYWORD_MODE = uci:get(appname, "@global_subscribe[0]", "fi local DEFAULT_FILTER_KEYWORD_DISCARD_LIST = uci:get(appname, "@global_subscribe[0]", "filter_discard_list") or {} local DEFAULT_FILTER_KEYWORD_KEEP_LIST = uci:get(appname, "@global_subscribe[0]", "filter_keep_list") or {} -- Nodes should be retrieved using the core type (if not set on the node subscription page, the default type will be used automatically). -local DEFAULT_SS_TYPE = api.get_core("ss_type", {{has_ss,"shadowsocks-libev"},{has_ss_rust,"shadowsocks-rust"},{has_singbox,"sing-box"},{has_xray,"xray"}}) +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"}}) local DEFAULT_VMESS_TYPE = api.get_core("vmess_type", {{has_xray,"xray"},{has_singbox,"sing-box"}}) local DEFAULT_VLESS_TYPE = api.get_core("vless_type", {{has_xray,"xray"},{has_singbox,"sing-box"}}) @@ -44,7 +43,6 @@ local DEFAULT_HYSTERIA2_TYPE = api.get_core("hysteria2_type", {{has_hysteria2,"h local core_has = { ["xray"] = has_xray, ["sing-box"] = has_singbox, - ["shadowsocks-libev"] = has_ss, ["shadowsocks-rust"] = has_ss_rust, ["hysteria2"] = has_hysteria2 } @@ -460,9 +458,7 @@ end -- Configure the SS protocol implementation type local function set_ss_implementation(ss_type, result) - if ss_type == "shadowsocks-libev" and has_ss then - result.type = "SS" - elseif ss_type == "shadowsocks-rust" and has_ss_rust then + if ss_type == "shadowsocks-rust" and has_ss_rust then result.type = 'SS-Rust' elseif ss_type == "xray" and has_xray then result.type = 'Xray' @@ -485,6 +481,7 @@ local function parseClashNode(node, add_mode, group, sub_cfg) local sub_vmess_type = DEFAULT_VMESS_TYPE local sub_vless_type = DEFAULT_VLESS_TYPE local sub_hysteria2_type = DEFAULT_HYSTERIA2_TYPE + local sub_hy_up_mbps, sub_hy_down_mbps = 1000, 1000 if sub_cfg then if sub_cfg.allowInsecure and sub_cfg.allowInsecure ~= "1" then sub_allowinsecure = nil @@ -509,6 +506,8 @@ local function parseClashNode(node, add_mode, group, sub_cfg) if hysteria2_type ~= "global" and core_has[hysteria2_type] then sub_hysteria2_type = hysteria2_type end + sub_hy_up_mbps = sub_cfg.hysteria_up_mbps + sub_hy_down_mbps = sub_cfg.hysteria_down_mbps end local result = { timeout = 60, @@ -778,6 +777,7 @@ local function processData(szType, content, add_mode, group, sub_cfg) local sub_vmess_type = DEFAULT_VMESS_TYPE local sub_vless_type = DEFAULT_VLESS_TYPE local sub_hysteria2_type = DEFAULT_HYSTERIA2_TYPE + local sub_hy_up_mbps, sub_hy_down_mbps = 1000, 1000 if sub_cfg then if sub_cfg.allowInsecure and sub_cfg.allowInsecure ~= "1" then sub_allowinsecure = nil @@ -802,6 +802,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) if hysteria2_type ~= "global" and core_has[hysteria2_type] then sub_hysteria2_type = hysteria2_type end + sub_hy_up_mbps = sub_cfg.hysteria_up_mbps + sub_hy_down_mbps = sub_cfg.hysteria_down_mbps end local result = { timeout = 60, @@ -1113,20 +1115,6 @@ local function processData(szType, content, add_mode, group, sub_cfg) end end - if result.type == "SS" then - local aead2022_methods = { "2022-blake3-aes-128-gcm", "2022-blake3-aes-256-gcm", "2022-blake3-chacha20-poly1305" } - local aead2022 = false - for k, v in ipairs(aead2022_methods) do - if method:lower() == v:lower() then - aead2022 = true - end - end - if aead2022 then - -- shadowsocks-libev does not support 2022 encryption. - result.error_msg = i18n.translatef("shadowsocks-libev unsupport 2022 encryption.") - end - end - if params.type then params.type = string.lower(params.type) if result.type == "sing-box" and params.type == "raw" then @@ -1140,7 +1128,7 @@ local function processData(szType, content, add_mode, group, sub_cfg) else result.transport = params.type end - if result.type ~= "SS-Rust" and result.type ~= "SS" then + if result.type ~= "SS-Rust" then if params.type == 'ws' then result.ws_host = params.host result.ws_path = params.path @@ -1647,8 +1635,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) local insecure = params.allowinsecure or params.allowInsecure or params.insecure result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") result.alpn = params.alpn - result.hysteria_up_mbps = params.upmbps - result.hysteria_down_mbps = params.downmbps + result.hysteria_up_mbps = params.upmbps or sub_hy_up_mbps + result.hysteria_down_mbps = params.downmbps or sub_hy_down_mbps result.hysteria_hop = params.mport elseif szType == 'hysteria2' or szType == 'hy2' then @@ -1692,6 +1680,8 @@ local function processData(szType, content, add_mode, group, sub_cfg) result.tls_CertByName = params.vcn local insecure = params.allowinsecure or params.insecure result.tls_allowInsecure = (insecure == "1" or insecure == "0") and insecure or (sub_allowinsecure and "1" or "0") + result.hysteria2_up_mbps = params.upmbps or sub_hy_up_mbps + result.hysteria2_down_mbps = params.downmbps or sub_hy_down_mbps result.hysteria2_hop = params.mport if params["obfs-password"] or params["obfs_password"] then result.hysteria2_obfs_type = "salamander" @@ -2180,7 +2170,7 @@ local function update_node(manual) local list = v["list"] local sub_cfg = v["sub_cfg"] local domain_resolver, domain_resolver_dns, domain_resolver_dns_https, domain_strategy - local preproxy_node_group, to_node_group, chain_node_type = "", "", "" + local preproxy_node_group, to_node_group, outbound_iface_group, chain_node_type = "", "", "", "" -- Subscription Group Chain Agent local function valid_chain_node(node) if not node then return "" end @@ -2200,6 +2190,8 @@ local function update_node(manual) domain_strategy = (sub_cfg.domain_strategy == "UseIPv4" or sub_cfg.domain_strategy == "UseIPv6") and sub_cfg.domain_strategy or nil preproxy_node_group = (sub_cfg.chain_proxy == "1") and valid_chain_node(sub_cfg.preproxy_node) or "" to_node_group = (sub_cfg.chain_proxy == "2") and valid_chain_node(sub_cfg.to_node) or "" + outbound_iface_group = (sub_cfg.chain_proxy == "3") and sub_cfg.outbound_iface or "" + chain_node_type = (outbound_iface_group ~= "") and "iface" or chain_node_type end for _, vv in ipairs(list) do local cfgid = uci:section(appname, "nodes", api.gen_short_uuid()) @@ -2235,6 +2227,9 @@ local function update_node(manual) elseif to_node_group ~= "" then uci:set(appname, cfgid, "chain_proxy", "2") uci:set(appname, cfgid, "to_node", to_node_group) + elseif outbound_iface_group ~= "" then + uci:set(appname, cfgid, "chain_proxy", "3") + uci:set(appname, cfgid, "outbound_iface", outbound_iface_group) end end end