diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua index cfb2ea4e2..00ef47d6a 100644 --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/advanced.lua @@ -1,5 +1,8 @@ local uci = luci.model.uci.cursor() local server_table = {} +local function is_finded(e) + return luci.sys.exec('type -t -p "%s"' % e) ~= "" and true or false +end uci:foreach("shadowsocksr", "servers", function(s) if s.alias then diff --git a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua index fa81be4a9..3bdb464cc 100644 --- a/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua +++ b/luci-app-ssr-plus/luasrc/model/cbi/shadowsocksr/client-config.lua @@ -117,7 +117,8 @@ local securitys = { local tls_flows = { -- tls "xtls-rprx-vision", - "xtls-rprx-vision-udp443" + "xtls-rprx-vision-udp443", + "none" } m = Map("shadowsocksr", translate("Edit ShadowSocksR Server")) @@ -218,7 +219,7 @@ o:depends("type", "ss") o:depends("type", "v2ray") o:depends("type", "trojan") o:depends("type", "naiveproxy") -o:depends({type = "hysteria",port_hopping = false}) +o:depends("type", "hysteria") o:depends("type", "tuic") o:depends("type", "shadowtls") o:depends("type", "socks5") @@ -341,7 +342,7 @@ o.default = "30" o = s:option(Value, "port_range", translate("Port Range")) o:depends({type = "hysteria", port_hopping = true}) -o.rmempty = false +o.rmempty = true o = s:option(Flag, "lazy_mode", translate("Enable Lazy Mode")) o:depends("type", "hysteria") @@ -868,7 +869,7 @@ if is_finded("xray") then o:depends({type = "v2ray", v2ray_protocol = "vless", reality = true}) -- [[ XTLS ]]-- - o = s:option(Value, "tls_flow", translate("Flow")) + o = s:option(ListValue, "tls_flow", translate("Flow")) for _, v in ipairs(tls_flows) do o:value(v, translate(v)) end @@ -878,7 +879,7 @@ if is_finded("xray") then -- [[ uTLS ]]-- o = s:option(Value, "fingerprint", translate("Finger Print")) - o:value("", translate("disable")) + o.default = "chrome" o:value("chrome", translate("chrome")) o:value("firefox", translate("firefox")) o:value("safari", translate("safari")) @@ -889,6 +890,7 @@ if is_finded("xray") then o:value("qq", translate("qq")) o:value("random", translate("random")) o:value("randomized", translate("randomized")) + o:value("", translate("disable")) o:depends({type = "v2ray", tls = true}) o:depends({type = "v2ray", reality = true}) end @@ -917,9 +919,11 @@ o = s:option(Value, "pinsha256", translate("Certificate fingerprint")) o:depends({type = "hysteria", insecure = true }) o.rmempty = true + -- [[ Mux ]]-- o = s:option(Flag, "mux", translate("Mux")) o.rmempty = false +o.default = false o:depends({type = "v2ray", v2ray_protocol = "vless"}) o:depends({type = "v2ray", v2ray_protocol = "vmess"}) o:depends({type = "v2ray", v2ray_protocol = "trojan"}) @@ -927,12 +931,185 @@ o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"}) o:depends({type = "v2ray", v2ray_protocol = "socks"}) o:depends({type = "v2ray", v2ray_protocol = "http"}) -o = s:option(Value, "concurrency", translate("Concurrency")) -o.datatype = "uinteger" +o = s:option(ListValue, "concurrency", translate("concurrency")) o.rmempty = true -o.default = "4" -o:depends("mux", "1") -o:depends("type", "naiveproxy") +o.default = "-1" +o:value("-1", translate("disable")) +o:value("8", translate("8")) +o:depends("mux", true) + +o = s:option(ListValue, "xudpConcurrency", translate("xudpConcurrency")) +o.rmempty = true +o.default = "16" +o:value("16", translate("16")) +o:value("-1", translate("disable")) +o:depends("mux", true) + +o = s:option(ListValue, "xudpProxyUDP443", translate("xudpProxyUDP443")) +o.rmempty = true +o.default = "reject" +o:value("reject", translate("reject")) +o:value("allow", translate("allow")) +o:value("skip", translate("skip")) +o:depends("mux", true) + + +-- [[ MPTCP ]]-- +o = s:option(Flag, "mptcp", translate("MPTCP")) +o.rmempty = false +o.default = false +o:depends({type = "v2ray", v2ray_protocol = "vless"}) +o:depends({type = "v2ray", v2ray_protocol = "vmess"}) +o:depends({type = "v2ray", v2ray_protocol = "trojan"}) +o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"}) +o:depends({type = "v2ray", v2ray_protocol = "socks"}) +o:depends({type = "v2ray", v2ray_protocol = "http"}) + +-- [[ custom_tcpcongestion 连接服务器节点的 TCP 拥塞控制算法 ]]-- +o = s:option(ListValue, "custom_tcpcongestion", translate("custom_tcpcongestion")) +o.rmempty = true +o.default = "" +o:value("", translate("comment_tcpcongestion_disable")) +o:value("bbr", translate("BBR")) +o:value("cubic", translate("CUBIC")) +o:value("reno", translate("Reno")) +o:depends({type = "v2ray", v2ray_protocol = "vless"}) +o:depends({type = "v2ray", v2ray_protocol = "vmess"}) +o:depends({type = "v2ray", v2ray_protocol = "trojan"}) +o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"}) +o:depends({type = "v2ray", v2ray_protocol = "socks"}) +o:depends({type = "v2ray", v2ray_protocol = "http"}) + + +-- [[ custom_sniffing 流量嗅探 ]]-- +o = s:option(Flag, "custom_sniffing", translate("custom_sniffing")) +o.rmempty = false +o.default = true +o:depends({type = "v2ray", v2ray_protocol = "vless"}) +o:depends({type = "v2ray", v2ray_protocol = "vmess"}) +o:depends({type = "v2ray", v2ray_protocol = "trojan"}) +o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"}) +o:depends({type = "v2ray", v2ray_protocol = "socks"}) +o:depends({type = "v2ray", v2ray_protocol = "http"}) + +-- [[ custom_domainsExcluded 流量嗅探域名排除列表 ]]-- +o = s:option(Flag, "custom_domainsExcluded", translate("custom_domainsExcluded")) +o.rmempty = false +o.default = true +o:depends("custom_sniffing", true) + +-- [[ custom_routeOnly 嗅探得到的域名仅用于 Xray 路由 ]]-- +o = s:option(Flag, "custom_routeOnly", translate("custom_routeOnly")) +o.rmempty = false +o.default = false +o:depends("custom_sniffing", true) + + +-- [[ custom_dns_enable Xray DNS 功能 ]]-- +o = s:option(Flag, "custom_dns_enable", translate("custom_dns_enable")) +o.rmempty = false +o.default = false +o:depends({type = "v2ray", v2ray_protocol = "vless"}) +o:depends({type = "v2ray", v2ray_protocol = "vmess"}) +o:depends({type = "v2ray", v2ray_protocol = "trojan"}) +o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"}) +o:depends({type = "v2ray", v2ray_protocol = "socks"}) +o:depends({type = "v2ray", v2ray_protocol = "http"}) +o.description = translate("comment_dns_inbound_enable") + +-- [[ custom_dns_local 本地 DNS ]]-- +o = s:option(ListValue, "custom_dns_local", translate("custom_dns_local")) +o.rmempty = true +o.default = "https+local://223.5.5.5/dns-query" +o:value("https+local://223.5.5.5/dns-query", translate("https+local://223.5.5.5/dns-query")) +o:value("https+local://119.29.29.29/dns-query", translate("https+local://119.29.29.29/dns-query")) +o:depends("custom_dns_enable", true) + +-- [[ custom_dns_remote 远端 DNS ]]-- +o = s:option(ListValue, "custom_dns_remote", translate("custom_dns_remote")) +o.rmempty = true +o.default = "https://1.1.1.1/dns-query" +o:value("https://1.1.1.1/dns-query", translate("https://1.1.1.1/dns-query")) +o:value("https://8.8.8.8/dns-query", translate("https://8.8.8.8/dns-query")) +o:depends("custom_dns_enable", true) + +-- [[ custom_dns_remote_domains 远端 DNS 域名列表 ]]-- +o = s:option(ListValue, "custom_dns_remote_domains", translate("custom_dns_remote_domains")) +o.rmempty = true +o.default = "geosite:geolocation-!cn" +o:value("geosite:geolocation-!cn", translate("geosite:geolocation-!cn")) +o:depends("custom_dns_enable", true) + +-- [[ custom_nonIPQuery 非 A 和 AAAA 记录处理方式 ]]-- +o = s:option(ListValue, "custom_nonIPQuery", translate("custom_nonIPQuery")) +o.rmempty = true +o.default = "skip" +o:value("skip", translate("skip")) +o:value("drop", translate("drop")) +o:depends("custom_dns_enable", true) + +-- [[ custom_nonIPQuery_outbound_tag 非 A 和 AAAA 记录查询方式 ]]-- +o = s:option(ListValue, "custom_nonIPQuery_outbound_tag", translate("custom_nonIPQuery_outbound_tag")) +o.rmempty = true +o.default = "direct" +o:value("direct", translate("direct")) +o:value("proxy", translate("proxy")) +o:depends({custom_nonIPQuery = "skip"}) + +-- [[ custom_dokodemo_door_dns_address 查询非 A 和 AAAA 记录 DNS ]]-- +o = s:option(ListValue, "custom_dokodemo_door_dns_address", translate("custom_dokodemo_door_dns_address")) +o.rmempty = true +o.default = "223.5.5.5" +o:value("223.5.5.5", translate("223.5.5.5")) +o:value("119.29.29.29", translate("119.29.29.29")) +o:value("1.1.1.1", translate("1.1.1.1")) +o:value("8.8.8.8", translate("8.8.8.8")) +o:depends({custom_nonIPQuery = "skip"}) + + +-- [[ custom_log Xray 日志功能 ]]-- +o = s:option(Flag, "custom_log", translate("custom_log")) +o.rmempty = false +o.default = false +o:depends({type = "v2ray", v2ray_protocol = "vless"}) +o:depends({type = "v2ray", v2ray_protocol = "vmess"}) +o:depends({type = "v2ray", v2ray_protocol = "trojan"}) +o:depends({type = "v2ray", v2ray_protocol = "shadowsocks"}) +o:depends({type = "v2ray", v2ray_protocol = "socks"}) +o:depends({type = "v2ray", v2ray_protocol = "http"}) + +-- [[ custom_loglevel 日志级别 ]]-- +o = s:option(ListValue, "custom_loglevel", translate("custom_loglevel")) +o.rmempty = true +o.default = "warning" +o:value("error", translate("error")) +o:value("warning", translate("warning")) +o:value("info", translate("info")) +o:value("debug", translate("debug")) +o:depends("custom_log", true) + +-- [[ custom_dnsLog DNS 查询记录 ]]-- +o = s:option(Flag, "custom_dnsLog", translate("custom_dnsLog")) +o.rmempty = true +o.default = true +o:depends("custom_log", true) + +-- [[ custom_access 访问记录 ]]-- +o = s:option(ListValue, "custom_access", translate("custom_access")) +o.rmempty = true +o.default = "/tmp/access.log" +o:value("/tmp/access.log", translate("/tmp/access.log")) +o:value("none", translate("none")) +o:depends("custom_log", true) + +-- [[ custom_error 错误记录 ]]-- +o = s:option(ListValue, "custom_error", translate("custom_error")) +o.rmempty = true +o.default = "/tmp/error.log" +o:value("/tmp/error.log", translate("/tmp/error.log")) +o:value("none", translate("none")) +o:depends("custom_log", true) + -- [[ Cert ]]-- o = s:option(Flag, "certificate", translate("Self-signed Certificate")) diff --git a/luci-app-ssr-plus/po/zh-cn/ssr-plus.po b/luci-app-ssr-plus/po/zh-cn/ssr-plus.po index aa317d88b..f03a33a55 100644 --- a/luci-app-ssr-plus/po/zh-cn/ssr-plus.po +++ b/luci-app-ssr-plus/po/zh-cn/ssr-plus.po @@ -91,6 +91,21 @@ msgstr "允许不安全连接" msgid "Concurrency" msgstr "最大并发连接数" +msgid "custom_tcpcongestion" +msgstr "连接服务器节点的 TCP 拥塞控制算法" + +msgid "comment_tcpcongestion_disable" +msgstr "使用系统默认值" + +msgid "custom_sniffing" +msgstr "流量嗅探" + +msgid "custom_domainsExcluded" +msgstr "流量嗅探域名排除列表" + +msgid "custom_routeOnly" +msgstr "嗅探得到的域名仅用于 Xray 内部路由" + msgid "If true, allowss insecure connection at TLS client, e.g., TLS server uses unverifiable certificates." msgstr "是否允许不安全连接。当选择时,将不会检查远端主机所提供的 TLS 证书的有效性。" diff --git a/luci-app-ssr-plus/root/etc/init.d/shadowsocksr b/luci-app-ssr-plus/root/etc/init.d/shadowsocksr index 8b007d96b..56153d37f 100755 --- a/luci-app-ssr-plus/root/etc/init.d/shadowsocksr +++ b/luci-app-ssr-plus/root/etc/init.d/shadowsocksr @@ -407,7 +407,7 @@ start_udp() { hysteria) gen_config_file $UDP_RELAY_SERVER $type 2 $tmp_udp_port ln_start_bin $(first_type hysteria) hysteria client --config $udp_config_file - echolog "UDP TPROXY Relay:$($(first_type "hysteria") version | awk '{print $1,$2}') Started!" + echolog "UDP TPROXY Relay:$($(first_type "hysteria") version | awk '{print "Hhysteria2: " $2}' | head -9 | tail +9) Started!" ;; tuic) # FIXME: ipt2socks cannot handle udp reply from tuic @@ -705,7 +705,7 @@ Start_Run() { hysteria) gen_config_file $GLOBAL_SERVER $type 1 $tcp_port $socks_port ln_start_bin $(first_type hysteria) hysteria client --config $tcp_config_file - echolog "Main node:$($(first_type hysteria) version | awk '{print $1,$2}') Started!" + echolog "Main node:$($(first_type hysteria) version | awk '{print "Hhysteria2: " $2}' | head -9 | tail +9) Started!" ;; tuic) local PARAM diff --git a/luci-app-ssr-plus/root/etc/uci-defaults/luci-ssr-plus b/luci-app-ssr-plus/root/etc/uci-defaults/luci-ssr-plus index 157774d12..72b338183 100755 --- a/luci-app-ssr-plus/root/etc/uci-defaults/luci-ssr-plus +++ b/luci-app-ssr-plus/root/etc/uci-defaults/luci-ssr-plus @@ -28,7 +28,6 @@ touch /etc/ssrplus/ad.conf touch /etc/config/shadowsocksr [ -s "/etc/config/shadowsocksr" ] || /etc/init.d/shadowsocksr reset -sed -i "s/option pdnsd_enable '3'/option pdnsd_enable '1'/g" /etc/config/shadowsocksr sed -i "s/option type 'vmess'/option type 'v2ray'\n\toption v2ray_protocol 'vmess'/g" /etc/config/shadowsocksr sed -i "s/option type 'vless'/option type 'v2ray'\n\toption v2ray_protocol 'vless'/g" /etc/config/shadowsocksr sed -i "s/option encrypt_method_v2ray_ss/option encrypt_method_ss/g" /etc/config/shadowsocksr diff --git a/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua b/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua index 1e1878c43..02603c3cf 100755 --- a/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua +++ b/luci-app-ssr-plus/root/usr/share/shadowsocksr/gen_config.lua @@ -116,18 +116,96 @@ end local settings = outbound:new() settings:handleIndex(server.v2ray_protocol) local Xray = { - log = { - -- error = "/var/ssrplus.log", - loglevel = "warning" + -- 日志 + log = (server.custom_log == "1") and { + loglevel = server.custom_loglevel, -- 日志级别 + dnsLog = (server.custom_dnsLog == "1") and true or false, -- DNS 查询记录 + access = server.custom_access, -- 访问记录 + error = server.custom_error -- 错误记录 + } or nil, + -- DNS + dns = { + hosts = { + ["dns.alidns.com"] = "223.5.5.5", + ["doh.pub"] = "119.29.29.29" + }, + servers = (server.custom_dns_enable == "1") and { -- Xray 内置 DNS + server.custom_dns_local, -- 本地 DNS + { + address = server.custom_dns_remote, -- 远端 DNS + domains = { + server.custom_dns_remote_domains -- 远端 DNS 域名列表 + }, + skipFallback = true, + queryStrategy = "UseIP" + } + } or nil, + queryStrategy = "UseIP" + }, + -- 路由 + routing = { + domainStrategy = "AsIs", + rules = { + { + type = "field", + inboundTag = { + "dns-in" + }, + outboundTag = "dns-out" + } + } }, -- 传入连接 - inbound = (local_port ~= "0") and { + inbounds = { + (local_port ~= "0") and { -- listening port = tonumber(local_port), protocol = "dokodemo-door", settings = {network = proto, followRedirect = true}, - sniffing = {enabled = true, destOverride = {"http", "tls"}} + sniffing = { + enabled = (server.custom_sniffing == "1") and true or false, -- 流量嗅探 + routeOnly = (server.custom_routeOnly == "1") and true or false, -- 嗅探得到的域名仅用于 Xray 内部路由 + destOverride = {"http", "tls", "quic"}, + domainsExcluded = (server.custom_domainsExcluded == "1") and { -- 流量嗅探域名排除列表 + "courier.push.apple.com", + "rbsxbxp-mim.vivox.com", + "rbsxbxp.www.vivox.com", + "rbsxbxp-ws.vivox.com", + "rbspsxp.www.vivox.com", + "rbspsxp-mim.vivox.com", + "rbspsxp-ws.vivox.com", + "rbswxp.www.vivox.com", + "rbswxp-mim.vivox.com", + "disp-rbspsp-5-1.vivox.com", + "disp-rbsxbp-5-1.vivox.com", + "proxy.rbsxbp.vivox.com", + "proxy.rbspsp.vivox.com", + "proxy.rbswp.vivox.com", + "rbswp.vivox.com", + "rbsxbp.vivox.com", + "rbspsp.vivox.com", + "rbspsp.www.vivox.com", + "rbswp.www.vivox.com", + "rbsxbp.www.vivox.com", + "rbsxbxp.vivox.com", + "rbspsxp.vivox.com", + "rbswxp.vivox.com", + "Mijia Cloud", + "dlg.io.mi.com" + } or nil, + } } or nil, + (server.custom_dns_enable == "1") and { -- Xray 内置 DNS + port = 5335, + protocol = "dokodemo-door", + settings = { + address = server.custom_dokodemo_door_dns_address, -- 查询非 A 和 AAAA 记录DNS + port = 53, + network = "udp" + }, + tag = "dns-in" + } or nil, + }, -- 开启 socks 代理 inboundDetour = (proto:find("tcp") and socks_port ~= "0") and { { @@ -138,7 +216,9 @@ local Xray = { } } or nil, -- 传出连接 - outbound = { + outbounds = { + { + tag = "proxy", protocol = server.v2ray_protocol, settings = outbound_settings, -- 底层传输配置 @@ -154,10 +234,9 @@ local Xray = { certificates = server.certificate and { usage = "verify", certificateFile = server.certpath - } or nil + } or nil, } or nil, realitySettings = (server.reality == '1') and { - show = false, publicKey = server.reality_publickey, shortId = server.reality_shortid, spiderX = server.reality_spiderx, @@ -176,6 +255,7 @@ local Xray = { } } or nil, kcpSettings = (server.transport == "kcp") and { + -- kcp mtu = tonumber(server.mtu), tti = tonumber(server.tti), uplinkCapacity = tonumber(server.uplink_capacity), @@ -217,14 +297,47 @@ local Xray = { health_check_timeout = tonumber(server.health_check_timeout) or nil, permit_without_stream = (server.permit_without_stream == "1") and true or nil, initial_windows_size = tonumber(server.initial_windows_size) or nil - } or nil + } or nil, + sockopt = { + tcpMptcp = (server.mptcp == "1") and true or false, -- MPTCP + tcpNoDelay = (server.mptcp == "1") and true or false, -- MPTCP + tcpcongestion = server.custom_tcpcongestion -- 连接服务器节点的 TCP 拥塞控制算法 + } }, - mux = (server.mux == "1" and server.transport ~= "grpc") and { - -- mux - enabled = true, - concurrency = tonumber(server.concurrency) - } or nil - } or nil + mux = { + enabled = (server.mux == "1") and true or false, -- Mux + concurrency = tonumber(server.concurrency), -- TCP 最大并发连接数 + xudpConcurrency = tonumber(server.xudpConcurrency), -- UDP 最大并发连接数 + xudpProxyUDP443 = server.xudpProxyUDP443 -- 对被代理的 UDP/443 流量处理方式 + } + }, + { + protocol = "freedom", + settings = { + domainStrategy = "ForceIPv6v4" + }, + streamSettings = { + sockopt = { + tcpFastOpen = true + } + }, + tag = "direct" + }, + { + protocol = "blackhole", + tag = "block" + }, + (server.custom_dns_enable == "1") and { -- Xray 内置 DNS + protocol = "dns", + settings = { + nonIPQuery = server.custom_nonIPQuery -- 非 A 和 AAAA 记录处理方式 + }, + proxySettings = (server.custom_nonIPQuery == "skip") and { + tag = server.custom_nonIPQuery_outbound_tag -- 非 A 和 AAAA 记录查询方式 + } or nil, + tag = "dns-out" + } or nil, + } } local cipher = "ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES128-SHA:ECDHE-RSA-AES256-SHA:DHE-RSA-AES128-SHA:DHE-RSA-AES256-SHA:AES128-SHA:AES256-SHA:DES-CBC3-SHA" local cipher13 = "TLS_AES_128_GCM_SHA256:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_256_GCM_SHA384" @@ -279,7 +392,7 @@ local ss = { reuse_port = true } local hysteria = { - server = server.server_port and (server.server .. ":" .. server.server_port) or (server.server .. ":" .. server.port_range), + server = (server.port_range and (server.server .. ":" .. server.port_range)) or (server.server_port and (server.server .. ":" .. server.server_port)), bandwidth = { up = tonumber(server.uplink_capacity) and tonumber(server.uplink_capacity) .. " mbps" or nil, down = tonumber(server.downlink_capacity) and tonumber(server.downlink_capacity) .. " mbps" or nil @@ -321,6 +434,7 @@ local hysteria = { auth = server.hy2_auth, tls = (server.tls_host) and { sni = server.tls_host, + alpn = server.tls_alpn or nil, insecure = (server.insecure == "1") and true or false, pinSHA256 = (server.insecure == "1") and server.pinsha256 or nil } or {