luci-app-ssr-plus: Add fake-ip mode and Fix Upload yaml config cannot use external DNS resolution. - #2043
luci-app-ssr-plus: Add fake-ip mode and Fix Upload yaml config cannot use external DNS resolution.#2043zxlhhyccc wants to merge 1 commit into
Conversation
… use external DNS resolution.
|
@zxlhhyccc 真机测试完成,发现三个问题,都已定位并验证修复。环境:ImmortalWrt 25.12.1 r37978-cd0a06bfd3fd,mihomo v1.19.30, 问题 1、2 用的是插件聚合生成的 Mihomo 总节点( 问题 1:
|
| nameserver-policy key | 结果 |
|---|---|
geosite:gfw |
failed |
geosite:cn |
successful |
geosite:apple |
successful |
geosite:cn,private,apple |
successful |
geosite:geolocation-!cn |
successful |
只有 gfw 不行。把
["geosite:gfw"] = result["fallback"] or get_forward_dns_list(),改成 ["geosite:geolocation-!cn"] 后配置校验通过、服务 3 秒内正常启动。语义上也等价(非中国大陆域名走 fallback)。
顺带一提,同一个函数里对 fallback-filter.geosite 已经做了 = nil 的兼容处理,nameserver-policy 这处漏了。
另外这个失败是完全静默的:生成的配置是 log-level: silent,而 init 脚本在 mihomo 真正加载配置之前就输出了 Main node: Mihomo v1.19.30 (Clash) Started!,所以日志里看不出任何异常,排查成本很高。建议 fake-ip 模式下至少把 log-level 提到 warning。
问题 2:陈旧的 nft 快照使 fake-ip 防火墙规则永不生效
修好问题 1 后服务能启动、DNS 也正确返回 198.18.0.x,但流量依然不通,nft 中 198.18.0.0/16 规则数为 0。
定位过程:在 fw_rule_nft() 首行插入 logger,从未触发(同时插在 ssr-rules 顶部的 logger 触发 3 次,且 enable_fake_ip 读到的值确实是 1),说明该函数根本没有被调用。
原因是 /usr/share/nftables.d/ruleset-post/99-shadowsocksr.nft —— 它是一个完整的 nft list ruleset 转储(147KB,连 counter packets 1 bytes 60 这样的计数器都被写进去了),由 fake-ip 关闭时生成。fw4 加载它之后,ssr-rules 检测到 ss_spec_wan_ac / jump ss_spec_wan_fw 已存在便跳过规则重建,因此切换 enable_fake_ip 对防火墙没有任何影响。
rm -f /usr/share/nftables.d/ruleset-post/99-shadowsocksr.nft
/etc/init.d/shadowsocksr restart之后 198.18.0.0/16 规则数从 0 变为 5:
ss_spec_wan_fw: ip daddr 198.18.0.0/16 meta l4proto tcp redirect to :1234
ss_spec_prerouting: iifname "br-lan" ip daddr 198.18.0.0/16 ip saddr @ss_spec_lan_ac meta l4proto tcp redirect to :1234
iifname "br-lan" ip daddr 198.18.0.0/16 ip saddr @ss_spec_lan_ac meta l4proto udp redirect to :1234
建议在 enable_fake_ip 变更时主动删除或重建这个持久化文件,否则所有在已有安装上开启 fake-ip 的用户都会遇到「fake-ip 不生效」,而且完全无从排查(服务正常运行、DNS 返回 fake-ip、日志无异常,只有流量不通)。
问题 3:订阅自带 dns 段时,listen 与 fake-ip-range 未被强制,DNS 链路完全断裂
把节点从插件聚合的总节点换成机场自带的 Clash 订阅(clash_url)后,所有 gfwlist 域名完全无法解析。
clash_yaml.lua 中这两个值都是「仅当订阅未提供时才设置」:
534: if not result["fake-ip-range"] then
535: result["fake-ip-range"] = "198.18.0.1/16"
612: if result.listen == nil or result.listen == "" then
613: result.listen = "127.0.0.1:5335"而我这份机场订阅的 dns 段自带 listen: 0.0.0.0:5053 和 fake-ip-range: 198.10.0.1/16,于是订阅的值存活下来,与插件其余部分硬编码的假设冲突:
| 插件硬编码 | 订阅提供 | 后果 | |
|---|---|---|---|
| DNS 端口 | dnsmasq 转发到 127.0.0.1#5335 |
mihomo 监听 0.0.0.0:5053 |
5335 Connection refused |
| fake-ip 网段 | ssr-rules 重定向 198.18.0.0/16 |
下发 198.10.0.x |
假 IP 永不被重定向 |
实测:
netstat: :::5053 LISTEN 6256/ssr-retcp ← mihomo 在 5053
dnsmasq: server=/google.com/127.0.0.1#5335 ← 却转发到 5335
5335: Connection refused
5053: zh.wikipedia.org -> 198.10.0.4
nft: 198.18.0.0/16 ← 重定向的是 198.18 段
53 解析被墙域名: (无结果)
curl https://www.google.com/generate_204 -> code=000
把 534 / 612 两处改为无条件强制后恢复正常:
fake-ip-range: 198.18.0.1/16
listen: 127.0.0.1:5335
netstat: 127.0.0.1:5335 LISTEN
nslookup zh.wikipedia.org 127.0.0.1 -> 198.18.0.8
nslookup -port=5335 zh.wikipedia.org -> 198.18.0.8
curl https://www.google.com/generate_204 -> code=204
curl https://zh.wikipedia.org/ -> code=301
curl https://api.mch.weixin.qq.com -> code=404(直连正常)
这两个值不是用户偏好,而是插件自身基础设施的对接点:listen 必须与 dnsmasq 的转发目标一致,fake-ip-range 必须与 ssr-rules 的重定向网段一致。订阅方无从得知这些约束,建议改为无条件覆盖(或者反过来:让 dnsmasq 与 ssr-rules 从实际生效的配置里读取这两个值)。
顺带一个安全性问题:订阅给的 listen: 0.0.0.0:5053 会让 mihomo DNS 监听所有接口(含 WAN),等于开放解析器;强制为 127.0.0.1 正好也修掉这一点。
三个问题修复后 fake-ip 在我这边工作正常,两种配置来源(clash_path 聚合节点 / clash_url 机场订阅)都验证过。感谢你的工作。
|
@gongdao123 请问你有Telegram联系方式吗?你说的1和2问题我还是不太明白,我用你的yaml配置上传后在ipt下能正常代理,nft下我没测试,所以想直接联系你确认一下情况。 |
|
@zxlhhyccc TG 收不到验证码,无法登录了。 |
|
@gongdao123 我在按你说的修正,明天你测试一下可以吗?因为我不是nft环境无法测试,nft规则我是凭感觉搞的。 |
|
好的 没问题,晚上回去测一下。我直接给你再打个pr好了? @zxlhhyccc |
@gongdao123 可以的。 |
|
@gongdao123 该PR我会删除,将重新提交PR,到时请测试。 |
|
@gongdao123 已重新提交PR,请测试,如有问题请及时反馈,没问题我就打算合并。见: #2044 |
No description provided.