fix(client-config): 加 route.default_domain_resolver(sing-box 1.12+ 必需)

sing-box 1.13 对缺失 default_domain_resolver 直接 FATAL。加 {"server":"local"}
后,节点下发的整份客户端配置经 `sing-box check` 验证通过(无 FATAL/废弃)。
顺带 local_test.sh:免密已生效则跳过(不再反复要密码)+ --no-build 快速重跑。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
wangjia
2026-06-18 21:35:50 +08:00
parent df72ad60f4
commit bdf67cb56e
2 changed files with 30 additions and 18 deletions
+26 -16
View File
@@ -4,7 +4,8 @@
# 用真正的 release 包(不是 dev 模拟),前台运行以便直接看内核(sing-box)日志。
# 改完代码直接跑此脚本即可。
#
# bash scripts/local_test.sh
# bash scripts/local_test.sh # 构建 release 并运行
# bash scripts/local_test.sh --no-build # 跳过构建,直接跑上次的产物(快速重跑)
#
# 可选环境变量:
# PANGOLIN_API_URL 控制面地址(默认连 racknerd 节点)
@@ -19,28 +20,37 @@ REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
CLIENT="$REPO_ROOT/client"
API_URL="${PANGOLIN_API_URL:-http://107.172.55.251:8080}"
SINGBOX="${SINGBOX_BIN:-/opt/homebrew/bin/sing-box}"
NO_BUILD=0
[ "${1:-}" = "--no-build" ] && NO_BUILD=1
command -v flutter >/dev/null 2>&1 || { echo "✗ 需要 flutter"; exit 1; }
[ -x "$SINGBOX" ] || { echo "✗ 找不到 sing-box: $SINGBOX(brew install sing-box,或设 SINGBOX_BIN)"; exit 1; }
# ── 1. TUN 免密 sudoers(幂等;命令路径须与客户端解析到的一致)──────────────────
echo "==> [1/3] 配置 sing-box 免密 sudo(TUN 需 root)"
SUDO_FILE=/etc/sudoers.d/pangolin-singbox
WANT="$(whoami) ALL=(root) NOPASSWD: $SINGBOX"
TMP="$(mktemp)"
printf '%s\n' "$WANT" > "$TMP"
# 校验语法后安装(避免写坏 sudoers)
if sudo visudo -cf "$TMP" >/dev/null 2>&1; then
sudo install -m 440 -o root -g wheel "$TMP" "$SUDO_FILE"
echo " 已写入 $SUDO_FILE: $WANT"
# ── 1. TUN 免密 sudoers(已生效则跳过,避免反复要密码)─────────────────────────
echo "==> [1/3] sing-box 免密 sudo(TUN 需 root)"
if sudo -n "$SINGBOX" version >/dev/null 2>&1; then
echo " 已生效,跳过(无需密码)"
else
echo "✗ sudoers 语法校验失败"; rm -f "$TMP"; exit 1
SUDO_FILE=/etc/sudoers.d/pangolin-singbox
WANT="$(whoami) ALL=(root) NOPASSWD: $SINGBOX"
TMP="$(mktemp)"
printf '%s\n' "$WANT" > "$TMP"
if sudo visudo -cf "$TMP" >/dev/null 2>&1; then
sudo install -m 440 -o root -g wheel "$TMP" "$SUDO_FILE"
echo " 已写入 $SUDO_FILE: $WANT"
else
echo "✗ sudoers 语法校验失败"; rm -f "$TMP"; exit 1
fi
rm -f "$TMP"
fi
rm -f "$TMP"
# ── 2. 构建 release ───────────────────────────────────────────────────────────
echo "==> [2/3] flutter build macos --release (API=$API_URL)"
( cd "$CLIENT" && flutter build macos --release --dart-define=PANGOLIN_API_URL="$API_URL" )
# ── 2. 构建 release(--no-build 跳过,直接跑上次产物)─────────────────────────
if [ "$NO_BUILD" = "1" ]; then
echo "==> [2/3] 跳过构建(--no-build)"
else
echo "==> [2/3] flutter build macos --release (API=$API_URL)"
( cd "$CLIENT" && flutter build macos --release --dart-define=PANGOLIN_API_URL="$API_URL" )
fi
APP="$(ls -d "$CLIENT"/build/macos/Build/Products/Release/*.app 2>/dev/null | head -1)"
[ -n "$APP" ] || { echo "✗ 未找到构建产物 .app"; exit 1; }
+4 -2
View File
@@ -114,8 +114,10 @@ func BuildClientConfig(node *nodes.NodeRow, dpUUID, deriveKey string) ([]byte, e
"outbound": "direct",
},
},
"final": "auto",
"auto_detect_interface": true,
"final": "auto",
"auto_detect_interface": true,
// sing-box 1.12+ 要求显式声明出站域名用哪个 DNS 解析,缺失即 FATAL。
"default_domain_resolver": map[string]any{"server": "local"},
}
// DNS: remote over tunnel, local for domestic.