Skip to content

Tailscale advertise_routes 报 invalid Prefix:getlanip 返回裸 IP 缺少 CIDR 前缀 #1256

@urjoe

Description

@urjoe

Bug 描述

在 Merlin 路由器(RT-AX86U Pro)上使用 ShellCrash 1.9.4 + SingBoxR 内核 1.13.2 配置 Tailscale 时,Tailscale 后台 Subnet routes 显示 "invalid Prefix",无法 approve,导致只能走 DERP 中继。

复现步骤

  1. 启用 Tailscale(crash → 7 → 6),开启 Subnet 通告
  2. 重启 ShellCrash
  3. 在 Tailscale 后台查看设备的 Edit route settings
  4. Subnet routes 显示 "invalid Prefix",点 Approve 报错 "Failed to update route settings"

根因分析

sb_endpoints.sh 通过 fw_getlanip.shgetlanip 函数获取本机路由表,生成 advertise_routes

路由表中点对点路由(WireGuard、PPPoE)不带 CIDR 前缀:

$ ip route show scope link
10.6.0.2 dev wgs1              ← 裸 IP,无 /32
10.6.0.3 dev wgs1              ← 裸 IP,无 /32
x.x.x.x dev ppp0          ← 裸 IP,无 /32
192.168.50.0/24 dev br0        ← 正常 CIDR

sb_endpoints.sh 直接将 $host_ipv4 拼入 JSON:

"advertise_routes": ["10.6.0.2", "10.6.0.3", "x.x.x.x", "192.168.50.0/24"]

sing-box 的 Tailscale endpoint 要求 advertise_routes 使用 netip.ParsePrefix() 解析,必须是 CIDR 格式,裸 IP 会导致解析失败。

建议修复

sb_endpoints.shgetlanip 调用之后、advertise_routes 赋值之前,给裸 IP 补上 /32

注意:Merlin 的 BusyBox sed 不支持 \+ 语法,需使用 awk:

. "$CRASHDIR"/starts/fw_getlanip.sh && getlanip
# 给没有 CIDR 前缀的裸 IP 补 /32
host_ipv4=$(echo $host_ipv4 | awk '{for(i=1;i<=NF;i++){if($i !~ /\//){$i=$i"/32"}} print}')
advertise_routes=$(echo "$host_ipv4"|sed 's/[[:space:]]\+/", "/g; s/^/"/; s/$/"/')

修复后:

"advertise_routes": ["10.6.0.2/32", "10.6.0.3/32", "x.x.x.x/32", "192.168.50.0/24"]

环境信息

  • 路由器:Asus RT-AX86U Pro (Merlin)
  • ShellCrash 版本:1.9.4release
  • 内核:SingBoxR 1.13.2
  • 受影响文件:libs/sb_endpoints.shstarts/fw_getlanip.sh

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions