Master#488
Conversation
luci-app-ssr-plus: Fix the issue where Xray nodes with download IP cannot proxie.
luci-app-ssr-plus: Fix `TUIC` configuration and subscribe.
tuic-client: update to 1.6.5
luci-app-ssr-plus: optimize the enabling logic of xray flow
Removed NEO DEV HOST Lite as it was deleted upstream.
Update advanced.lua
luci-app-ssr-plus: perform simple fault-tolerant processing for xray xhttp extra
luci-app-ssr-plus: Fix configuration issue of vmess protocol.
The path to the LuCI index cache file has changed to /tmp/luci-indexcache.*.json since OpenWrt 22.03.
luci-app-ssr-plus: Fix up/down and add top/bottom.
luci-app-ssr-plus: Optimize server list code.
luci-app-ssr-plus: add Xray pre-connect (testpre).
…un due to persistence rules when using NFTS.
luci-app-ssr-plus: Add noises 'Hex' Encode.
luci-app-ssr-plus: Smart core select and import/subscribe stability enhance.
luci-app-ssr-plus: hysteria2 hopInterval support range
luci-app-ssr-plus: Optimize the code for generate NFT persistence rules.
luci-app-ssr-plus: Fix UDP rules.
luci-app-ssr-plus: optimize node user-agent config options
luci-app-ssr-plus: add node domain specify DNS option
…ts rarely used config options
luci-app-ssr-plus: add `cwndmultiplier` support for mkcp and remove its rarely used config options
luci-app-ssr-plus: improve curl success handling in subscribe_update.
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request primarily focuses on updating various network proxy and DNS tool packages to their latest upstream versions to ensure security and performance. Additionally, it introduces significant functional improvements to the luci-app-ssr-plus package, including enhanced node management capabilities, better firewall backend compatibility (nftables/iptables), and more flexible core selection logic for modern protocols like Hysteria2 and Trojan. Highlights
New Features🧠 You can now enable Memory (public preview) to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console. Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize the Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counterproductive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. Footnotes
|
There was a problem hiding this comment.
Code Review
此拉取请求对 luci-app-ssr-plus 进行了全面重构与功能增强,主要变动包括:引入 nftables 防火墙后端支持及规则持久化逻辑;重构服务器列表 UI,通过 Sortable.min.js 实现拖拽排序及置顶功能;增强了 Hysteria2 协议支持,包括新增连接测试脚本;优化 Xray 配置生成逻辑,支持 FinalMask、ECH 及自定义 DNS 解析;并同步更新了 xray-core、mosdns 等多个核心组件版本。反馈建议:在 act_ping、act_save_order 及订阅脚本中存在多处未转义用户输入直接拼接 shell 命令的情况,存在命令注入风险,应使用 luci.util.shellquote() 处理;此外,初始化脚本中的临时文件应存放在 /tmp 目录以兼容只读文件系统。
| grep -vE '^\s*#|^\s*$' "$list_file" > "${list_file}.clean" | ||
| if [ -s "${list_file}.clean" ]; then | ||
| grep -v -F -f "${list_file}.clean" "$TMP_DNSMASQ_PATH/ad.conf" > "$TMP_DNSMASQ_PATH/ad.conf.tmp" | ||
| mv "$TMP_DNSMASQ_PATH/ad.conf.tmp" "$TMP_DNSMASQ_PATH/ad.conf" | ||
| fi | ||
| rm -f "${list_file}.clean" |
There was a problem hiding this comment.
在 /etc/ssrplus/ 目录下创建临时文件 ${list_file}.clean。如果该目录位于只读文件系统(如 SquashFS)上,此操作将失败。建议将临时文件存放在 /tmp/ 目录下。
| grep -vE '^\s*#|^\s*$' "$list_file" > "${list_file}.clean" | |
| if [ -s "${list_file}.clean" ]; then | |
| grep -v -F -f "${list_file}.clean" "$TMP_DNSMASQ_PATH/ad.conf" > "$TMP_DNSMASQ_PATH/ad.conf.tmp" | |
| mv "$TMP_DNSMASQ_PATH/ad.conf.tmp" "$TMP_DNSMASQ_PATH/ad.conf" | |
| fi | |
| rm -f "${list_file}.clean" | |
| local clean_file="/tmp/$(basename "$list_file").clean" | |
| grep -vE '^\s*#|^\s*$' "$list_file" > "$clean_file" | |
| if [ -s "$clean_file" ]; then | |
| grep -v -F -f "$clean_file" "$TMP_DNSMASQ_PATH/ad.conf" > "$TMP_DNSMASQ_PATH/ad.conf.tmp" | |
| mv "$TMP_DNSMASQ_PATH/ad.conf.tmp" "$TMP_DNSMASQ_PATH/ad.conf" | |
| fi | |
| rm -f "$clean_file" |
There was a problem hiding this comment.
Pull request overview
本 PR 集中升级了多个上游代理工具的版本,并对 luci-app-ssr-plus 中的防火墙/分流脚本和测速能力做了较大重构,新增了 Hysteria2 节点测速脚本,同时调整了 tuic-client 的 cargo 构建命令与架构支持列表。
Changes:
- 升级
xray-core、v2ray-core、v2raya、v2ray-plugin、xray-plugin、shadowsocks-rust、naiveproxy(含 clang/PGO 资源)、mosdns、tuic-client、redsocks2等包的版本与哈希。 - 重构
chinaipset.sh、gfw2ipset.sh:通过check_run_environment/USE_TABLES统一 nft/iptables 选择,使用grep -v -F -f批量过滤black/white/deny/netflix.list,并按run_mode分别处理ipset/nftset指令。 - 新增
hy2_test.sh用于 Hysteria2 节点 URL 测试;在shadowsocksr.config默认配置中加入prefer_nft与url_test_url;调整tuic-client的DEPENDS、Select/Features写法与Build/Compile(移除TARGET_CFLAGS/RUSTC_CFLAGS)。
Reviewed changes
Copilot reviewed 33 out of 38 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| xray-core/Makefile | 升级 xray-core 至 26.5.9,更新 PKG_HASH |
| xray-plugin/Makefile | 更新 PKG_HASH |
| v2ray-core/Makefile | 升级 v2ray-core 至 5.47.0 |
| v2ray-plugin/Makefile | 升级至 5.48.0 |
| v2raya/Makefile | 升级 v2rayA 至 2.2.7.5 并更新前端资源 HASH |
| tuic-client/Makefile | 升级至 1.7.2,重写架构判断与特性选择,删除 TARGET_CFLAGS 行 |
| shadowsocks-rust/Makefile | 升级至 1.24.0 |
| redsocks2/Makefile | 升级 git 源版本到 2025-12-12 |
| naiveproxy/Makefile | 升级至 147.0.7727.49-1,并更新 CLANG/PGO 资源 |
| mosdns/Makefile | 升级至 5.3.4 |
| mosdns/patches/203-...patch | 调整补丁上下文行号以适配新版本 |
| luci-app-ssr-plus/.../shadowsocksr.config | 默认开启 prefer_nft,新增 url_test_url 默认值 |
| luci-app-ssr-plus/.../hy2_test.sh | 新增 Hysteria2 节点 URL 测试脚本 |
| luci-app-ssr-plus/.../gfw2ipset.sh | 重写防火墙后端检测与分流列表过滤逻辑 |
| luci-app-ssr-plus/.../chinaipset.sh | 改造为支持 nftables/iptables 双后端,按 SKIP_INET 切换 set 命名空间 |
| local max_port=49151 | ||
| local port="$1" | ||
| local protocol=$(echo "$2" | tr 'A-Z' 'a-z') | ||
| local LOCK_FILE="${LOCK_PATH}/${CONFIG}_get_prot.lock" |
| # kill -9 $pid 2>/dev/null | ||
| local pid_file="/tmp/hy2_test_${node_id}.pid" | ||
| [ -s "$pid_file" ] && kill -9 "$(head -n 1 "$pid_file")" >/dev/null 2>&1 | ||
| pgrep -af "hysteria.*${config_file}" | awk '! /test\.sh/{print $1}' | xargs kill -9 >/dev/null 2>&1 |
| # 此处使用 for 方式读取 防止 /etc/ssrplus/ 目录下的 black.list white.list deny.list 等2个或多个文件一行中存在空格 比如:# abc.com 而丢失:server | ||
| # Optimize: Batch filter using grep |
| for list_file in /etc/ssrplus/black.list /etc/ssrplus/white.list /etc/ssrplus/deny.list; do | ||
| if [ -s "$list_file" ]; then | ||
| grep -vE '^\s*#|^\s*$' "$list_file" > "${list_file}.clean" | ||
| if [ -s "${list_file}.clean" ]; then | ||
| for target_file in "$TMP_DNSMASQ_PATH/gfw_list.conf" "$TMP_DNSMASQ_PATH/gfw_base.conf"; do | ||
| if [ -f "$target_file" ]; then | ||
| grep -v -F -f "${list_file}.clean" "$target_file" > "${target_file}.tmp" | ||
| mv "${target_file}.tmp" "$target_file" | ||
| fi | ||
| done | ||
| fi | ||
| rm -f "${list_file}.clean" | ||
| fi | ||
| done |
There was a problem hiding this comment.
这个点我认同。现在这段从按行 sed 删除,变成了 grep -v -F -f 的子串过滤,语义已经变了。像列表里如果有比较短的内容,确实可能把本来不该删的规则整行一起滤掉。这里最好按域名字段精确匹配,不然这种误删很难排查。
| netflix() { | ||
| if [ -f "$TMP_DNSMASQ_PATH/gfw_list.conf" ]; then | ||
| for line in $(cat /etc/ssrplus/netflix.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_list.conf; done | ||
| for line in $(cat /etc/ssrplus/netflix.list); do sed -i "/$line/d" $TMP_DNSMASQ_PATH/gfw_base.conf; done | ||
| local port="$1" | ||
| if [ -f "$TMP_DNSMASQ_PATH/gfw_list.conf" ] && [ -s /etc/ssrplus/netflix.list ]; then | ||
| grep -vE '^\s*#|^\s*$' /etc/ssrplus/netflix.list > /tmp/ssrplus_netflix.list.clean | ||
| if [ -s /tmp/ssrplus_netflix.list.clean ]; then | ||
| grep -v -F -f /tmp/ssrplus_netflix.list.clean "$TMP_DNSMASQ_PATH/gfw_list.conf" > "$TMP_DNSMASQ_PATH/gfw_list.conf.tmp" | ||
| mv "$TMP_DNSMASQ_PATH/gfw_list.conf.tmp" "$TMP_DNSMASQ_PATH/gfw_list.conf" | ||
| if [ -f "$TMP_DNSMASQ_PATH/gfw_base.conf" ]; then | ||
| grep -v -F -f /tmp/ssrplus_netflix.list.clean "$TMP_DNSMASQ_PATH/gfw_base.conf" > "$TMP_DNSMASQ_PATH/gfw_base.conf.tmp" | ||
| mv "$TMP_DNSMASQ_PATH/gfw_base.conf.tmp" "$TMP_DNSMASQ_PATH/gfw_base.conf" | ||
| fi | ||
| fi | ||
| rm -f /tmp/ssrplus_netflix.list.clean | ||
| fi |
| cargo build --release \ | ||
| -p tuic-client \ | ||
| --target $(RUSTC_TARGET_ARCH) \ | ||
| $(call Select/Features) ; \ |
|
@codex 请review pr,用简体中文 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4c9db8282f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| function act_restart() | ||
| luci.sys.call("/etc/init.d/shadowsocksr restart &") | ||
| luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr")) | ||
| end |
| if params.fm and params.fm ~= "" then | ||
| result.enable_finalmask = "1" | ||
| result.finalmaskg = base64Encode(params.fm) |
There was a problem hiding this comment.
There was a problem hiding this comment.
| if ss_type == "ss-rust" or ss_type == "ss-libev" then | ||
| xray_ss_type = ss_type | ||
| else | ||
| xray_ss_type = has_ss_rust and "ss-rust" or "ss-libev" |
| if has_hysteria2 then | ||
| o:value("trojan", translate("Trojan")) | ||
| end |
| local has_ss_libev = luci.sys.exec('type -t -p ss-redir 2>/dev/null || type -t -p ss-local 2>/dev/null') ~= "" | ||
| local has_hysteria = luci.sys.exec('type -t -p hysteria 2>/dev/null') ~= "" | ||
| local has_trojan = luci.sys.exec('type -t -p trojan 2>/dev/null') ~= "" | ||
| local has_xray = luci.sys.exec('type -t -p xray 2>/dev/null') ~= "" |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 4c9db8282f
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
|
|
||
| function act_restart() | ||
| luci.sys.call("/etc/init.d/shadowsocksr restart &") | ||
| luci.http.redirect(luci.dispatcher.build_url("admin", "services", "shadowsocksr")) |
| if has_hysteria2 then | ||
| o:value("trojan", translate("Trojan")) |
There was a problem hiding this comment.
Use the Trojan availability flag
When editing the per-node Trojan core preference on a system that has trojan installed but not hysteria, this check suppresses the Trojan choice because it is gated on the Hysteria2 binary instead of has_trojan. Conversely, systems with Hysteria2 but no Trojan are offered an unavailable Trojan core, so the UI can no longer accurately select the installed Trojan implementation.
Useful? React with 👍 / 👎.
| end | ||
| alias = alias .. remarks | ||
| result.alias = alias | ||
| raw_alias = raw_alias .. remarks |
There was a problem hiding this comment.
Initialize the SSR alias before concatenating
For SSR subscription links without a group parameter, raw_alias is never initialized before this concatenation, so processData() raises a nil-concatenation error and the subscription update aborts for that node. If a previous SSR node did set raw_alias, this also reuses stale state; build the alias from a local empty string as before.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
这个问题也是真 bug。这里前面只初始化了 local alias = "",后面却直接拿 raw_alias = raw_alias .. remarks 来拼;如果没有 group,raw_alias 一开始就是 nil,直接就会报错。就算刚好没炸,也有可能串到前一次的值。这里还是得回到局部变量自己初始化,不要吃外面的状态。
| -- 检查 finalmaskg 参数是否存在且非空 | ||
| if params.fm and params.fm ~= "" then | ||
| result.enable_finalmask = "1" | ||
| result.finalmaskg = base64Encode(params.fm) |
There was a problem hiding this comment.
Store imported FinalMask under the used option
When an imported Shadowsocks URL includes fm=, this branch enables FinalMask but writes the payload to finalmaskg, while the CBI model and gen_config.lua read the option named finalmask. As a result subscribed nodes silently lose their custom FinalMask configuration; the same typo should be corrected anywhere this import path writes the option.
Useful? React with 👍 / 👎.
| DNSMASQ_IPSET=0; [[ "$dnsmasq_info" == *" ipset"* ]] && DNSMASQ_IPSET=1 | ||
| DNSMASQ_NFTSET=0; [[ "$dnsmasq_info" == *" nftset"* ]] && DNSMASQ_NFTSET=1 |
There was a problem hiding this comment.
Avoid bash-only tests in the init script
OpenWrt init scripts run under /bin/sh/ash, where [[ ... ]] is not available. In that environment these tests fail as commands, leaving both DNSMASQ capability flags at 0; check_run_environment() then never selects either nftables or iptables, so SSR Plus starts without installing the transparent proxy firewall rules.
Useful? React with 👍 / 👎.
| if info.type and info.type == "dns" then | ||
| result.kcp_guise = info.host or "" | ||
| end | ||
| result.seed = params.seed |
There was a problem hiding this comment.
Do not read
params in the vmess branch
For any subscribed vmess node using KCP transport, this line indexes params, but params is only defined in other protocol branches and is nil here. That makes KCP vmess imports abort with an attempt-to-index-nil error instead of adding the node.
Useful? React with 👍 / 👎.
No description provided.