Skip to content

fix(ssr-plus): 修复 gRPC 节点订阅更新后 serviceName 丢失导致 xray 启动失败 - #2042

Open
fordjkhjk wants to merge 1 commit into
fw876:devfrom
fordjkhjk:fix/grpc-servicename
Open

fix(ssr-plus): 修复 gRPC 节点订阅更新后 serviceName 丢失导致 xray 启动失败#2042
fordjkhjk wants to merge 1 commit into
fw876:devfrom
fordjkhjk:fix/grpc-servicename

Conversation

@fordjkhjk

Copy link
Copy Markdown

问题

从订阅更新节点后,trojan-grpc / vless-grpc 节点必然启动失败,界面显示「未运行」,且无任何日志提示。实机排查发现是两个连环 bug:

根因

1. subscribe.lua —— serviceName 键名大小写不匹配,永远取到 nil

三处 gRPC 分支(trojan/vless/hysteria2 解析)存储查询参数时用 params[string.lower(t[1])] 把键名统一转成小写(如 servicename),读取时却用驼峰 params.serviceName,键名对不上,所有 gRPC 节点的 serviceName 解析结果恒为 nil。

2. gen_config.lua —— 空 grpcSettings 被序列化成 JSON 数组,xray 拒收退出

serviceName 为 nil 时,grpcSettings 表内字段可能全为 nil,luci.jsonc 会把这样的空表编码成 JSON 数组 [](而非对象 {}),xray 24.x+ 配置校验失败直接退出进程。

两个 bug 叠加:订阅更新 → serviceName 丢失 → xray 崩溃 → 「未运行」,用户完全无法定位原因。

修复

  • subscribe.lua(3 处):params.serviceName 改为 params.serviceName or params.servicename or params.path,兼容大小写两种键名(path 与 serviceName 在多数机场链接中同值);
  • gen_config.lua(1 处):serviceName 兜底为空字符串 "",保证 grpcSettings 始终序列化为 JSON 对象。

实机验证

  • ImmortalWrt + xray 24.x 实机,修补后订阅重新解析,gRPC 节点 serviceName 正确写入配置;
  • xray 正常常驻运行,通过节点 socks5 端口连测 https://www.google.com/generate_204 返回 204。

…ing xray

Two chained bugs causing trojan-grpc / vless-grpc nodes to fail
silently after a subscription update:

1. subscribe.lua: query params are stored with lowercased keys
   (params[string.lower(t[1])]) but read back as camelCase
   params.serviceName, so serviceName always resolves to nil for
   every gRPC node parsed from a subscription.

2. gen_config.lua: when serviceName is nil, the grpcSettings table
   may end up with all fields nil; luci.jsonc then serializes it as
   a JSON array [] instead of an object, which xray (24.x+) rejects
   and exits. The UI only shows "not running" with no error log.

Fix:
- fall back to lowercase/path keys when reading serviceName
- default serviceName to empty string so grpcSettings always
  serializes as a JSON object

Verified on a real device (ImmortalWrt, xray 24.x): after
re-parsing the subscription, gRPC handshake succeeds and socks5
connectivity test returns 204.
@zxlhhyccc

zxlhhyccc commented Sep 5, 2026

Copy link
Copy Markdown
Collaborator

@fordjkhjk
1、关于订阅。订阅通过params[string.lower(t[1])] 把键名统一转成小写,只有 1717 行所在的节点 trojan 函数改成了小写,其他的都没改(其他改成小写的不受影响),不要对没改的添加无谓的参数。另外,1717行直接将: result.serviceName = params.servicename 即可,就是说,其他1382和1855行请不要动。
2、关于生成配置。不要乱改为"",保留 or nil,其意思是如果无serviceName,不生成 serviceName 配置。
请修改并重新提交PR。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants