feat: bind_interface-only by default + WWAN watch auto-rebind
- Default BIND_SOURCE_IP=false: do not pin inet4_bind_address (stale
source IP after WWAN re-dial was the main rep=0x01 cause).
- Add scripts/watch-cellular.sh: ip monitor events + poll, regenerate
when iface missing or pinned source IP drifts.
- systemd: cellular-proxy-watch.service + 2min timer oneshot fallback.
- cpxy watch {status|once|start|stop|logs}
- Install/upgrade enable watch when ENABLE_CELLULAR_WATCH=true.
This commit is contained in:
+18
-6
@@ -14,22 +14,33 @@ if [[ -z "$cell" ]]; then
|
||||
resolve_cellular >/dev/null || true
|
||||
fi
|
||||
|
||||
# 始终以当前网卡实 IP 为准:WWAN 重拨后 iface 名常不变,但 CELLULAR_SOURCE_IP 会过期。
|
||||
# 过期的 inet4_bind_address 会导致 sing-box 出站失败 → 客户端 SOCKS rep=0x01。
|
||||
# 绑定策略(优先更好的实现,而不是只靠定时器修 stale IP):
|
||||
# 默认 BIND_SOURCE_IP=false → 只写 bind_interface,不写 inet4_bind_address。
|
||||
# sing-box 1.11+ 在 wwan 重拨后仍能按网卡出口,无需锁定私网源 IP。
|
||||
# 实测:去掉 inet4_bind_address 后 SOCKS 仍从数据出口出(公网 IP ≠ WiFi)。
|
||||
# BIND_SOURCE_IP=true 时才 pin 源 IP(兼容特殊内核/多地址场景),并始终用 live IP。
|
||||
live_src=""
|
||||
if [[ -n "$cell" ]]; then
|
||||
live_src="$(detect_source_ip "$cell" || true)"
|
||||
fi
|
||||
src_ip="${live_src:-${CELLULAR_SOURCE_IP:-}}"
|
||||
BIND_SOURCE_IP="$(echo "${BIND_SOURCE_IP:-false}" | tr '[:upper:]' '[:lower:]')"
|
||||
if [[ -n "$cell" && -n "$live_src" && "${CELLULAR_SOURCE_IP:-}" != "$live_src" ]]; then
|
||||
info "源 IP 已漂移: ${CELLULAR_SOURCE_IP:-<空>} → $live_src,写回 settings"
|
||||
info "源 IP 记录更新: ${CELLULAR_SOURCE_IP:-<空>} → $live_src(settings 仅作元数据)"
|
||||
persist_cellular_to_settings "${CONFIG_FILE:-$ROOT_DIR/etc/settings.conf}" "$cell" "$live_src" || true
|
||||
# 兼容 live 安装布局:settings 在 etc/
|
||||
if [[ -f /opt/cellular-proxy/etc/settings.conf ]]; then
|
||||
persist_cellular_to_settings /opt/cellular-proxy/etc/settings.conf "$cell" "$live_src" || true
|
||||
fi
|
||||
CELLULAR_SOURCE_IP="$live_src"
|
||||
fi
|
||||
# 默认不把源 IP 写进 sing-box,避免下次重拨 stale bind
|
||||
GEN_SRC_FOR_CFG=""
|
||||
if [[ "$BIND_SOURCE_IP" == "true" || "$BIND_SOURCE_IP" == "1" || "$BIND_SOURCE_IP" == "yes" ]]; then
|
||||
GEN_SRC_FOR_CFG="$src_ip"
|
||||
info "BIND_SOURCE_IP=true → pin inet4_bind_address=${GEN_SRC_FOR_CFG:-<空>}"
|
||||
else
|
||||
info "绑定模式: bind_interface only(不 pin 源 IP,重拨更稳)"
|
||||
fi
|
||||
|
||||
if [[ -z "$cell" ]]; then
|
||||
warn "CELLULAR_IFACE 为空,临时用 lo 生成配置(启动前务必修正)"
|
||||
@@ -47,7 +58,7 @@ fi
|
||||
|
||||
export GEN_OUT="$OUT_DIR/config.json"
|
||||
export GEN_CELL="$cell_for_cfg"
|
||||
export GEN_SRC="$src_ip"
|
||||
export GEN_SRC="${GEN_SRC_FOR_CFG:-}"
|
||||
export GEN_PROXY_HOST="$PROXY_LISTEN_HOST"
|
||||
export GEN_PROXY_PORT="$PROXY_MIXED_PORT"
|
||||
export GEN_PROXY_USER="$PROXY_USER"
|
||||
@@ -83,12 +94,13 @@ inbound = {
|
||||
if users:
|
||||
inbound["users"] = users
|
||||
|
||||
# 唯一业务出口:强制绑定数据网卡
|
||||
# 唯一业务出口:强制绑定数据网卡(默认仅 bind_interface)
|
||||
out_cell = {
|
||||
"type": "direct",
|
||||
"tag": "cellular",
|
||||
"bind_interface": cell,
|
||||
}
|
||||
# 仅当 GEN_SRC 非空(BIND_SOURCE_IP=true)时 pin 源 IP
|
||||
if src:
|
||||
out_cell["inet4_bind_address"] = src
|
||||
|
||||
|
||||
Reference in New Issue
Block a user