From c94416953e2d77c34fad1d447132769b925a49a2 Mon Sep 17 00:00:00 2001 From: action Date: Thu, 21 May 2026 10:49:42 +0800 Subject: [PATCH] update 2026-05-21 10:49:42 --- .../passwall/client/node_subscribe_config.lua | 8 + .../root/usr/share/passwall/subscribe.lua | 11 +- .../model/cbi/shadowsocksr/server-config.lua | 370 +++++++++++++++--- .../luasrc/model/cbi/shadowsocksr/server.lua | 11 +- .../root/etc/init.d/shadowsocksr | 177 +++++++++ luci-app-ssr-plus/root/usr/bin/ssr-monitor | 2 +- 6 files changed, 507 insertions(+), 72 deletions(-) diff --git a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua index 90858054..55a94368 100644 --- a/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua +++ b/luci-app-passwall/luasrc/model/cbi/passwall/client/node_subscribe_config.lua @@ -222,6 +222,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 PassWall runs automatically after each system boot.")) diff --git a/luci-app-passwall/root/usr/share/passwall/subscribe.lua b/luci-app-passwall/root/usr/share/passwall/subscribe.lua index 83dbdd2d..9e9e527a 100755 --- a/luci-app-passwall/root/usr/share/passwall/subscribe.lua +++ b/luci-app-passwall/root/usr/share/passwall/subscribe.lua @@ -505,6 +505,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 @@ -529,6 +530,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, @@ -1351,8 +1354,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 @@ -1396,8 +1399,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 - result.hysteria2_down_mbps = params.downmbps + 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" diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua index 71d8ccf5..2fdf777d 100644 --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server-config.lua @@ -7,68 +7,39 @@ require "nixio.fs" local m, s, o local sid = arg[1] +-- 加密方式(SS/SSR用) local encrypt_methods = { - "rc4-md5", - "rc4-md5-6", - "rc4", - "table", - "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", - "cast5-cfb", - "des-cfb", - "idea-cfb", - "rc2-cfb", - "seed-cfb", - "salsa20", - "chacha20", - "chacha20-ietf" + "rc4-md5", "rc4-md5-6", "rc4", "table", + "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", + "cast5-cfb", "des-cfb", "idea-cfb", "rc2-cfb", "seed-cfb", + "salsa20", "chacha20", "chacha20-ietf" } local encrypt_methods_ss = { - -- aead - "aes-128-gcm", - "aes-192-gcm", - "aes-256-gcm", - "chacha20-ietf-poly1305", - "xchacha20-ietf-poly1305", - -- aead 2022 - "2022-blake3-aes-128-gcm", - "2022-blake3-aes-256-gcm", - "2022-blake3-chacha20-poly1305" - --[[ stream - "table", - "rc4", - "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" ]] + "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" +} + +-- Shadowsocks 加密方法(Xray 版) +local v_ss_encrypt_method_list = { + "aes-128-cfb", "aes-256-cfb", "aes-128-gcm", "aes-256-gcm", + "chacha20", "chacha20-ietf", "chacha20-poly1305", "chacha20-ietf-poly1305" +} + +-- 伪装类型(用于 mKCP/QUIC) +local header_type_list = { + "none", "srtp", "utp", "wechat-video", "dtls", "wireguard" } local protocol = {"origin"} - obfs = {"plain", "http_simple", "http_post"} m = Map("shadowsocksr", translate("Edit ShadowSocksR Server")) - m.redirect = luci.dispatcher.build_url("admin/services/shadowsocksr/server") + if m.uci:get("shadowsocksr", sid) ~= "server_config" then luci.http.redirect(m.redirect) return @@ -79,6 +50,7 @@ s = m:section(NamedSection, sid, "server_config") s.anonymous = true s.addremove = false +-- ========== 基本设置 ========== o = s:option(Flag, "enable", translate("Enable")) o.default = 1 o.rmempty = false @@ -91,6 +63,13 @@ end if nixio.fs.access("/usr/bin/ssr-server") then o:value("ssr", translate("ShadowsocksR")) end +-- Xray 协议支持 +if nixio.fs.access("/usr/bin/xray") or nixio.fs.access("/usr/libexec/xray") then + o:value("vmess", "VMess (Xray)") + o:value("vless", "VLESS (Xray)") + o:value("trojan", "Trojan (Xray)") + o:value("shadowsocks", "Shadowsocks (Xray)") +end o.default = "socks5" o = s:option(Value, "server_port", translate("Server Port")) @@ -114,32 +93,30 @@ o:depends("type", "socks5") o = s:option(Value, "password", translate("Password")) o.password = true o.rmempty = false +o:depends("type", "socks5") +o:depends("type", "ss") +o:depends("type", "ssr") +o:depends("type", "trojan") +o:depends("type", "shadowsocks") +-- ========== SS/SSR 协议特有 ========== o = s:option(ListValue, "encrypt_method", translate("Encrypt Method")) -for _, v in ipairs(encrypt_methods) do - o:value(v) -end +for _, v in ipairs(encrypt_methods) do o:value(v) end o.rmempty = false o:depends("type", "ssr") o = s:option(ListValue, "encrypt_method_ss", translate("Encrypt Method")) -for _, v in ipairs(encrypt_methods_ss) do - o:value(v) -end +for _, v in ipairs(encrypt_methods_ss) do o:value(v) end o.rmempty = false o:depends("type", "ss") o = s:option(ListValue, "protocol", translate("Protocol")) -for _, v in ipairs(protocol) do - o:value(v) -end +for _, v in ipairs(protocol) do o:value(v) end o.rmempty = false o:depends("type", "ssr") o = s:option(ListValue, "obfs", translate("Obfs")) -for _, v in ipairs(obfs) do - o:value(v) -end +for _, v in ipairs(obfs) do o:value(v) end o.rmempty = false o:depends("type", "ssr") @@ -151,4 +128,269 @@ o.rmempty = false o:depends("type", "ss") o:depends("type", "ssr") -return m +-- ========== Xray 协议通用字段 ========== +-- 用户备注 +o = s:option(Value, "remarks", translate("Remarks")) +o.default = translate("Remarks") +o.rmempty = true +o:depends("type", "vmess") +o:depends("type", "vless") +o:depends("type", "trojan") +o:depends("type", "shadowsocks") + +-- 用户等级 +o = s:option(Value, "level", translate("User Level")) +o.datatype = "uinteger" +o.default = 1 +o.rmempty = true +o:depends("type", "vmess") +o:depends("type", "vless") +o:depends("type", "shadowsocks") +o:depends("type", "trojan") + +-- ========== Xray 协议认证字段 ========== +-- UUID (用于 vmess/vless) +o = s:option(Value, "uuid", translate("UUID")) +o.description = translate("Required for VMess/VLESS. Generate with: uuidgen") +o.rmempty = true +o:depends("type", "vmess") +o:depends("type", "vless") + +-- Trojan 密码 +o = s:option(Value, "trojan_password", translate("Trojan Password")) +o.password = true +o.rmempty = true +o:depends("type", "trojan") + +-- Shadowsocks 密码和加密(Xray 内置) +o = s:option(Value, "ss_password", translate("Shadowsocks Password")) +o.password = true +o.rmempty = true +o:depends("type", "shadowsocks") + +o = s:option(ListValue, "ss_method", translate("Encrypt Method")) +for _, v in ipairs(v_ss_encrypt_method_list) do o:value(v) end +o.default = "chacha20-ietf-poly1305" +o.rmempty = true +o:depends("type", "shadowsocks") + +o = s:option(ListValue, "ss_network", translate("Transport")) +o:value("tcp", "TCP") +o:value("udp", "UDP") +o:value("tcp,udp", "TCP,UDP") +o.default = "tcp,udp" +o.rmempty = true +o:depends("type", "shadowsocks") + +-- VMess alterId +o = s:option(Value, "alter_id", translate("Alter ID")) +o.datatype = "uinteger" +o.default = 0 +o.rmempty = true +o:depends("type", "vmess") + +-- VLESS decryption +o = s:option(Value, "decryption", translate("Decryption")) +o.default = "none" +o.rmempty = true +o:depends("type", "vless") + +-- ========== TLS / XTLS 设置 ========== +o = s:option(Flag, "tls", translate("TLS")) +o.default = 0 +o.rmempty = true +o:depends("type", "vmess") +o:depends("type", "vless") +o:depends("type", "trojan") +o:depends("type", "shadowsocks") + +o = s:option(Flag, "xtls", translate("XTLS")) +o.default = 0 +o.rmempty = true +o:depends({ type = "vless", tls = "1" }) + +o = s:option(ListValue, "flow", translate("Flow")) +o:value("xtls-rprx-origin", "xtls-rprx-origin") +o:value("xtls-rprx-origin-udp443", "xtls-rprx-origin-udp443") +o:value("xtls-rprx-direct", "xtls-rprx-direct") +o:value("xtls-rprx-direct-udp443", "xtls-rprx-direct-udp443") +o:value("xtls-rprx-splice", "xtls-rprx-splice") +o:value("xtls-rprx-splice-udp443", "xtls-rprx-splice-udp443") +o.default = "xtls-rprx-direct" +o.rmempty = true +o:depends("xtls", "1") + +o = s:option(Value, "tls_serverName", translate("Server Name (SNI)")) +o.rmempty = true +o:depends("tls", "1") + +o = s:option(Value, "tls_certificateFile", translate("Certificate File Path")) +o.description = translate("e.g.: /etc/ssl/fullchain.pem") +o.rmempty = true +o:depends("tls", "1") + +o = s:option(Value, "tls_keyFile", translate("Private Key File Path")) +o.description = translate("e.g.: /etc/ssl/private.key") +o.rmempty = true +o:depends("tls", "1") + +-- ========== 传输层设置 (Transport) ========== +o = s:option(ListValue, "transport", translate("Transport Protocol")) +o:value("tcp", "TCP") +o:value("mkcp", "mKCP") +o:value("ws", "WebSocket") +o:value("h2", "HTTP/2") +o:value("ds", "DomainSocket") +o:value("quic", "QUIC") +o.default = "tcp" +o.rmempty = true +o:depends("type", "vmess") +o:depends("type", "vless") +o:depends("type", "trojan") + +-- ----- WebSocket 设置 ----- +o = s:option(Value, "ws_host", translate("WebSocket Host")) +o.rmempty = true +o:depends("transport", "ws") +o:depends("type", "vmess") +o:depends("type", "vless") +o:depends("type", "trojan") + +o = s:option(Value, "ws_path", translate("WebSocket Path")) +o.default = "/" +o.rmempty = true +o:depends("transport", "ws") +o:depends("type", "vmess") +o:depends("type", "vless") +o:depends("type", "trojan") + +-- ----- HTTP/2 设置 ----- +o = s:option(Value, "h2_host", translate("HTTP/2 Host")) +o.rmempty = true +o:depends("transport", "h2") +o:depends("type", "vmess") +o:depends("type", "vless") + +o = s:option(Value, "h2_path", translate("HTTP/2 Path")) +o.default = "/" +o.rmempty = true +o:depends("transport", "h2") +o:depends("type", "vmess") +o:depends("type", "vless") + +-- ----- TCP 伪装设置 ----- +o = s:option(ListValue, "tcp_guise", translate("TCP Camouflage Type")) +o:value("none", "none") +o:value("http", "http") +o.default = "none" +o.rmempty = true +o:depends("transport", "tcp") +o:depends("type", "vmess") +o:depends("type", "vless") + +o = s:option(DynamicList, "tcp_guise_http_host", translate("HTTP Host")) +o.rmempty = true +o:depends("tcp_guise", "http") + +o = s:option(DynamicList, "tcp_guise_http_path", translate("HTTP Path")) +o.rmempty = true +o:depends("tcp_guise", "http") + +-- ----- mKCP 设置 ----- +o = s:option(ListValue, "mkcp_guise", translate("mKCP Camouflage Type")) +for _, v in ipairs(header_type_list) do o:value(v) end +o.default = "none" +o.rmempty = true +o:depends("transport", "mkcp") + +o = s:option(Value, "mkcp_mtu", translate("KCP MTU")) +o.datatype = "uinteger" +o.default = 1350 +o.rmempty = true +o:depends("transport", "mkcp") + +o = s:option(Value, "mkcp_tti", translate("KCP TTI")) +o.datatype = "uinteger" +o.default = 20 +o.rmempty = true +o:depends("transport", "mkcp") + +o = s:option(Value, "mkcp_uplinkCapacity", translate("KCP Uplink Capacity")) +o.datatype = "uinteger" +o.default = 5 +o.rmempty = true +o:depends("transport", "mkcp") + +o = s:option(Value, "mkcp_downlinkCapacity", translate("KCP Downlink Capacity")) +o.datatype = "uinteger" +o.default = 20 +o.rmempty = true +o:depends("transport", "mkcp") + +o = s:option(Flag, "mkcp_congestion", translate("KCP Congestion Control")) +o.default = 0 +o.rmempty = true +o:depends("transport", "mkcp") + +o = s:option(Value, "mkcp_readBufferSize", translate("KCP Read Buffer Size")) +o.datatype = "uinteger" +o.default = 1 +o.rmempty = true +o:depends("transport", "mkcp") + +o = s:option(Value, "mkcp_writeBufferSize", translate("KCP Write Buffer Size")) +o.datatype = "uinteger" +o.default = 1 +o.rmempty = true +o:depends("transport", "mkcp") + +o = s:option(Value, "mkcp_seed", translate("KCP Seed")) +o.datatype = "uinteger" +o.rmempty = true +o:depends("transport", "mkcp") + +-- ----- DomainSocket 设置 ----- +o = s:option(Value, "ds_path", translate("DomainSocket Path")) +o.description = translate("A legal file path. This file must not exist before running.") +o.rmempty = true +o:depends("transport", "ds") + +-- ----- QUIC 设置 ----- +o = s:option(ListValue, "quic_security", translate("QUIC Security")) +o:value("none", "none") +o:value("aes-128-gcm", "aes-128-gcm") +o:value("chacha20-poly1305", "chacha20-poly1305") +o.default = "none" +o.rmempty = true +o:depends("transport", "quic") + +o = s:option(Value, "quic_key", translate("QUIC Key")) +o.rmempty = true +o:depends("transport", "quic") + +o = s:option(ListValue, "quic_guise", translate("QUIC Camouflage Type")) +for _, v in ipairs(header_type_list) do o:value(v) end +o.default = "none" +o.rmempty = true +o:depends("transport", "quic") + +-- ========== 访问控制 ========== +o = s:option(Flag, "bind_local", translate("Bind Local Only")) +o.description = translate("When selected, it can only be accessed locally. Recommended when using reverse proxies.") +o.default = 0 +o.rmempty = true +o:depends("type", "vmess") +o:depends("type", "vless") +o:depends("type", "trojan") +o:depends("type", "shadowsocks") + +o = s:option(Flag, "accept_lan", translate("Accept LAN Access")) +o.description = translate("When selected, it can be accessed from LAN. This may not be safe!") +o.default = 0 +o.rmempty = true +o:depends("type", "vmess") +o:depends("type", "vless") +o:depends("type", "trojan") +o:depends("type", "shadowsocks") + +return m \ No newline at end of file diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua index db3160ab..c2ac03c6 100644 --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/server.lua @@ -105,8 +105,13 @@ end o.rmempty = false o = sec:option(DummyValue, "type", translate("Server Type")) -function o.cfgvalue(...) - return Value.cfgvalue(...) or "ss" +function o.cfgvalue(self, section) + local val = Value.cfgvalue(self, section) or "ss" + if val == "vmess" then return "VMess (Xray)" + elseif val == "vless" then return "VLESS (Xray)" + elseif val == "trojan" then return "Trojan (Xray)" + elseif val == "shadowsocks" then return "Shadowsocks (Xray)" + else return val end end o = sec:option(DummyValue, "server_port", translate("Server Port")) @@ -135,4 +140,4 @@ function o.cfgvalue(...) return Value.cfgvalue(...) or "-" end -return m +return m \ No newline at end of file diff --git a/luci-app-ssr-plus/root/etc/init.d/shadowsocksr b/luci-app-ssr-plus/root/etc/init.d/shadowsocksr index efa48187..b4cafdcc 100755 --- a/luci-app-ssr-plus/root/etc/init.d/shadowsocksr +++ b/luci-app-ssr-plus/root/etc/init.d/shadowsocksr @@ -985,6 +985,130 @@ start_dns() { fi } +# 鐢熸垚 Xray 鏈嶅姟绔厤缃� +# 鐢熸垚 Xray 鏈嶅姟绔厤缃� +generate_xray_config() { + local type="$1" + local port="$2" + local password="$3" + local security="$4" + local method="$5" + local network="$6" + local ws_path="$7" + local ws_host="$8" + local grpc_service="$9" + local alter_id="${10}" + local tcp_guise="${11}" + local tcp_guise_http_host="${12}" + local tcp_guise_http_path="${13}" + local config_file="${14}" + + local inbound_json="" + + case "$type" in + vmess) + inbound_json="{ + \"protocol\": \"vmess\", + \"port\": $port, + \"settings\": { + \"clients\": [{\"id\": \"$password\", \"alterId\": $alter_id}] + }, + \"streamSettings\": { + \"network\": \"$network\" + } + }" + ;; + vless) + inbound_json="{ + \"protocol\": \"vless\", + \"port\": $port, + \"settings\": { + \"clients\": [{\"id\": \"$password\"}], + \"decryption\": \"none\" + }, + \"streamSettings\": { + \"network\": \"$network\" + } + }" + ;; + trojan) + inbound_json="{ + \"protocol\": \"trojan\", + \"port\": $port, + \"settings\": { + \"clients\": [{\"password\": \"$password\"}] + }, + \"streamSettings\": { + \"network\": \"$network\" + } + }" + ;; + shadowsocks) + inbound_json="{ + \"protocol\": \"shadowsocks\", + \"port\": $port, + \"settings\": { + \"method\": \"$method\", + \"password\": \"$password\" + } + }" + ;; + *) + return 1 + ;; + esac + + # 娣诲姞浼犺緭灞傜粏鑺� + case "$network" in + ws) + local ws_json="{\"path\": \"$ws_path\"}" + [ -n "$ws_host" ] && ws_json="{\"path\": \"$ws_path\", \"headers\": {\"Host\": \"$ws_host\"}}" + inbound_json=$(echo "$inbound_json" | sed "s/\"streamSettings\": {/\"streamSettings\": {\"wsSettings\": $ws_json, /") + ;; + grpc) + [ -n "$grpc_service" ] && inbound_json=$(echo "$inbound_json" | sed "s/\"streamSettings\": {/\"streamSettings\": {\"grpcSettings\": {\"serviceName\": \"$grpc_service\"}, /") + ;; + tcp) + # TCP HTTP 浼 + if [ "$tcp_guise" = "http" ]; then + local tcp_json="{\"header\": {\"type\": \"http\"" + + # 娣诲姞 HTTP Host + if [ -n "$tcp_guise_http_host" ]; then + # 灏嗙┖鏍煎垎闅旂殑澶氫釜 host 杞崲涓� JSON 鏁扮粍鏍煎紡 + local host_list=$(echo "$tcp_guise_http_host" | sed 's/ /","/g') + tcp_json="$tcp_json, \"request\": {\"headers\": {\"Host\": [\"$host_list\"]}}" + fi + + # 娣诲姞 HTTP Path + if [ -n "$tcp_guise_http_path" ]; then + local path_list=$(echo "$tcp_guise_http_path" | sed 's/ /","/g') + tcp_json="$tcp_json, \"response\": {\"headers\": {\"Location\": [\"$path_list\"]}}" + fi + + tcp_json="$tcp_json}}" + inbound_json=$(echo "$inbound_json" | sed "s/\"streamSettings\": {/\"streamSettings\": {\"tcpSettings\": $tcp_json, /") + fi + ;; + esac + + cat > "$config_file" << EOF +{ + "log": { + "loglevel": "warning" + }, + "inbounds": [$inbound_json], + "outbounds": [ + { + "protocol": "freedom", + "settings": {} + } + ] +} +EOF + return 0 +} + gen_service_file() { #1-server.type 2-cfgname 3-file_path local fastopen if [ $(uci_get_by_name $2 fast_open) == "1" ]; then @@ -1875,6 +1999,59 @@ start_server() { ln_start_bin $(first_type microsocks) microsocks $listenip -p $(uci_get_by_name $1 server_port) -1 $auth_opts ssr-server$server_count echolog "Server:Socks5 Server$server_count Started!" ;; + vmess|vless|trojan|shadowsocks) + # Xray 鏈嶅姟绔敮鎸� + local port=$(uci_get_by_name "$1" server_port) + local uuid=$(uci_get_by_name "$1" uuid) + local trojan_pass=$(uci_get_by_name "$1" trojan_password) + local ss_pass=$(uci_get_by_name "$1" ss_password) + local security=$(uci_get_by_name "$1" security "auto") + local network=$(uci_get_by_name "$1" network "tcp") + local ws_path=$(uci_get_by_name "$1" ws_path "/") + local ws_host=$(uci_get_by_name "$1" ws_host "") + local grpc_service=$(uci_get_by_name "$1" grpc_service "") + local alter_id=$(uci_get_by_name "$1" alter_id "0") + local tcp_guise=$(uci_get_by_name "$1" tcp_guise "none") + local tcp_guise_http_host=$(uci_get_by_name "$1" tcp_guise_http_host "") + local tcp_guise_http_path=$(uci_get_by_name "$1" tcp_guise_http_path "") + + # 纭畾瀵嗙爜/UUID + local password="" + local method="" + if [ "$type" = "vmess" ] || [ "$type" = "vless" ]; then + password="$uuid" + elif [ "$type" = "trojan" ]; then + password="$trojan_pass" + elif [ "$type" = "shadowsocks" ]; then + password="$ss_pass" + method="$security" + [ -z "$method" ] && method="chacha20-ietf-poly1305" + fi + + [ -z "$password" ] && { + echolog "Server: $type 鏈嶅姟绔己灏戝瘑鐮�/UUID锛岃烦杩囧惎鍔�" + return 1 + } + + local config_file="$TMP_PATH/xray-server-$server_count.json" + + # 鐢熸垚 Xray 閰嶇疆 + generate_xray_config "$type" "$port" "$password" "$security" "$method" "$network" "$ws_path" "$ws_host" "$grpc_service" "$alter_id" "$tcp_guise" "$tcp_guise_http_host" "$tcp_guise_http_path" "$config_file" + + if [ $? -ne 0 ]; then + echolog "Server: Xray $type 閰嶇疆鐢熸垚澶辫触" + return 1 + fi + + local xray_bin=$(first_type xray) + if [ -z "$xray_bin" ]; then + echolog "Server: xray-core 鏈畨瑁咃紝鏃犳硶鍚姩 $type 鏈嶅姟绔�" + return 1 + fi + + ln_start_bin "$xray_bin" xray-server-$server_count run -c "$config_file" + echolog "Server: Xray $type 鏈嶅姟绔� Server$server_count 宸插惎鍔� (绔彛: $port)" + ;; esac server_port=$(uci_get_by_name $1 server_port) if [ "$USE_TABLES" = "nftables" ]; then diff --git a/luci-app-ssr-plus/root/usr/bin/ssr-monitor b/luci-app-ssr-plus/root/usr/bin/ssr-monitor index b045e20c..d9732d25 100755 --- a/luci-app-ssr-plus/root/usr/bin/ssr-monitor +++ b/luci-app-ssr-plus/root/usr/bin/ssr-monitor @@ -114,7 +114,7 @@ while [ "1" == "1" ]; do #姝诲惊鐜� fi #server if [ "$server_process_count" -gt 0 ]; then - icount=$(match_proc_count 'ssr-server|ss-server-') + icount=$(match_proc_count 'ssr-server|ss-server-|xray-server-') if [ "$icount" -lt "$server_process_count" ]; then #濡傛灉杩涚▼鎸傛帀灏遍噸鍚畠 logger -t "$NAME" "ssrplus server error.restart!" echolog "ssrplus server error.restart!"