Skip to content

Commit 1598632

Browse files
committed
feat(wifi): 按 WiFi SSID 自动开关代理(黑/白名单)
- netmon.sh(新增):inotifyd 监听 /data/misc/net/rt_tables 的写 事件感知网络切换,按当前 SSID + 黑/白名单决策 - cli:新增 wifi 命令组(status/on/off/mode/add/del/list/clear/cellular) - tproxy.conf:末尾独立扩展区存放 WiFi 配置,标注由 netmon.sh 读取 - customize.sh: netmon.sh 为可执行
1 parent c08e892 commit 1598632

5 files changed

Lines changed: 565 additions & 3 deletions

File tree

src/module/config/tproxy/tproxy.conf

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -107,4 +107,23 @@ BLOCK_QUIC=1
107107
# ===================== 调试模式 =====================
108108
DRY_RUN=0
109109
# 日志时间戳 (0: 禁用, 1: 启用)
110-
LOG_TIMESTAMP=0
110+
LOG_TIMESTAMP=0
111+
112+
# ##################################################################
113+
# # 以下为扩展功能配置,由 netmon.sh 读取,与上游 tproxy.sh 无关。
114+
# # (tproxy.sh 不识别这些键;放在末尾独立成区,便于区分与维护)
115+
# ##################################################################
116+
117+
# ===================== WiFi 自动切换代理 (netmon.sh) =====================
118+
# 按当前连接的 WiFi SSID 自动开/关代理 (黑/白名单)
119+
# 总开关 (0: 禁用, 1: 启用)
120+
WIFI_AUTO_SWITCH=0
121+
# 名单模式:
122+
# blacklist = 名单内 SSID 关闭代理(绕过),其余 WiFi 开启代理
123+
# whitelist = 仅名单内 SSID 开启代理,其余 WiFi 关闭代理(绕过)
124+
WIFI_SSID_MODE="blacklist"
125+
# SSID 名单 (英文逗号分隔,SSID 自身可含空格;全角逗号会自动归一化)
126+
# 例: WIFI_SSID_LIST="家里WiFi,Office 5G,Cafe"
127+
WIFI_SSID_LIST=""
128+
# 非 WiFi 网络(移动数据等)是否走代理 (0: 否/绕过, 1: 是/代理)
129+
PROXY_ON_CELLULAR=1

src/module/customize.sh

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ readonly EXECUTABLE_FILES="
4343
scripts/core/service.sh
4444
scripts/core/switch.sh
4545
scripts/network/tproxy.sh
46+
scripts/network/netmon.sh
4647
scripts/core/subscription.sh
4748
scripts/utils/ipset.sh
4849
scripts/utils/gms_fix.sh

src/module/scripts/cli

Lines changed: 192 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
# 功能: NetProxy 命令行工具,统一管理服务、节点、模式、订阅、
55
# 控制接口、分应用代理与透明代理等操作。
66
# 用法: cli <命令组> <子命令> [参数],详见 show_help。
7-
# 命令组: service / node / mode / sub / api / app / tproxy
7+
# 命令组: service / node / mode / sub / api / app / tproxy / wifi
88
# 依赖: common.sh、config.sh、api.sh、nodes.sh 及 core/network 下脚本。
99
#######################################
1010

@@ -227,6 +227,23 @@ show_app_help() {
227227
EOF
228228
}
229229

230+
# 显示 wifi 命令组帮助
231+
show_wifi_help() {
232+
cat << EOF
233+
用法:
234+
cli wifi status 查看 WiFi 自动切换配置与当前态
235+
cli wifi on | off 启用 / 禁用 WiFi 自动切换
236+
cli wifi mode <blacklist|whitelist> 设置名单模式
237+
cli wifi add <SSID> 添加 SSID 到名单
238+
cli wifi del <SSID> 从名单移除 SSID
239+
cli wifi list 列出名单
240+
cli wifi clear 清空名单
241+
cli wifi cellular <on|off> 非 WiFi 网络是否走代理
242+
说明:
243+
blacklist = 名单内 SSID 关代理、其余开;whitelist = 仅名单内开、其余关
244+
EOF
245+
}
246+
230247
# 显示 tproxy 命令组帮助
231248
show_tproxy_help() {
232249
cat << EOF
@@ -886,9 +903,173 @@ cmd_tproxy() {
886903
}
887904

888905
#######################################
889-
# 总帮助
906+
# wifi 命令 (按 SSID 自动开/关代理)
890907
#######################################
891908

909+
readonly NETMON_SCRIPT="$SCRIPTS_DIR/network/netmon.sh"
910+
911+
# 改动配置后应用:运行中则让 netmon 重启守护并即时评估,否则提示下次启动生效
912+
wifi_apply() {
913+
if is_running; then
914+
sh "$NETMON_SCRIPT" sync > /dev/null 2>&1 || warn "WiFi 自动切换应用失败"
915+
info "已应用 (即时生效)"
916+
else
917+
info "服务未运行,配置将在下次启动时生效"
918+
fi
919+
}
920+
921+
# 向逗号分隔名单添加 SSID (去重、归一化全角逗号)。参数: $1 原名单 $2 新增SSID
922+
wifi_list_add() {
923+
printf "%s" "$1" | sed 's/,/,/g' | awk -v add="$2" -F',' '
924+
BEGIN { OFS = "," }
925+
{
926+
for (i = 1; i <= NF; i++) {
927+
s = $i; sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s)
928+
if (s != "") { items[++n] = s; if (s == add) found = 1 }
929+
}
930+
}
931+
END {
932+
if (!found && add != "") items[++n] = add
933+
for (i = 1; i <= n; i++) printf "%s%s", (i > 1 ? OFS : ""), items[i]
934+
}
935+
'
936+
}
937+
938+
# 从逗号分隔名单移除 SSID。参数: $1 原名单 $2 待删SSID
939+
wifi_list_del() {
940+
printf "%s" "$1" | sed 's/,/,/g' | awk -v del="$2" -F',' '
941+
BEGIN { OFS = "," }
942+
{
943+
for (i = 1; i <= NF; i++) {
944+
s = $i; sub(/^[ \t]+/, "", s); sub(/[ \t]+$/, "", s)
945+
if (s != "" && s != del) items[++n] = s
946+
}
947+
}
948+
END { for (i = 1; i <= n; i++) printf "%s%s", (i > 1 ? OFS : ""), items[i] }
949+
'
950+
}
951+
952+
# 查看 WiFi 自动切换配置与当前态
953+
cmd_wifi_status() {
954+
local state
955+
section "WiFi 自动切换"
956+
printf "自动切换: %s\n" "$(read_conf "$TPROXY_CONF" "WIFI_AUTO_SWITCH" "0")"
957+
printf "名单模式: %s\n" "$(read_conf "$TPROXY_CONF" "WIFI_SSID_MODE" "blacklist")"
958+
printf "SSID 名单: %s\n" "$(read_conf "$TPROXY_CONF" "WIFI_SSID_LIST" "")"
959+
printf "非WiFi代理: %s\n" "$(read_conf "$TPROXY_CONF" "PROXY_ON_CELLULAR" "1")"
960+
# 运行中时按 iptables 实际规则显示当前态
961+
if is_running; then
962+
if iptables -t mangle -C PROXY_PREROUTING -j NETMON_BYPASS > /dev/null 2>&1 ||
963+
iptables -t nat -C PROXY_PREROUTING -j NETMON_BYPASS > /dev/null 2>&1; then
964+
state="bypassed (绕过代理)"
965+
else
966+
state="proxying (走代理)"
967+
fi
968+
printf "当前状态: %s\n" "$state"
969+
fi
970+
}
971+
972+
# 启用 WiFi 自动切换
973+
cmd_wifi_on() {
974+
set_conf "$TPROXY_CONF" "WIFI_AUTO_SWITCH" "1"
975+
info "WiFi 自动切换已启用"
976+
wifi_apply
977+
}
978+
979+
# 禁用 WiFi 自动切换
980+
cmd_wifi_off() {
981+
set_conf "$TPROXY_CONF" "WIFI_AUTO_SWITCH" "0"
982+
info "WiFi 自动切换已禁用"
983+
wifi_apply
984+
}
985+
986+
# 设置名单模式。参数: $1 blacklist/whitelist
987+
cmd_wifi_mode() {
988+
local mode="${1:-}"
989+
case "$mode" in
990+
blacklist | whitelist) ;;
991+
*) die_cli "用法: cli wifi mode <blacklist|whitelist>" ;;
992+
esac
993+
set_conf "$TPROXY_CONF" "WIFI_SSID_MODE" "$(quote_conf "$mode")"
994+
info "名单模式已设置为: $mode"
995+
wifi_apply
996+
}
997+
998+
# 添加 SSID 到名单。参数: $1 SSID
999+
cmd_wifi_add() {
1000+
local ssid="${1:-}"
1001+
local new_list
1002+
[ -n "$ssid" ] || die_cli "用法: cli wifi add <SSID>"
1003+
new_list="$(wifi_list_add "$(read_conf "$TPROXY_CONF" "WIFI_SSID_LIST" "")" "$ssid")"
1004+
set_conf "$TPROXY_CONF" "WIFI_SSID_LIST" "$(quote_conf "$new_list")"
1005+
info "已添加 SSID: $ssid"
1006+
wifi_apply
1007+
}
1008+
1009+
# 从名单移除 SSID。参数: $1 SSID
1010+
cmd_wifi_del() {
1011+
local ssid="${1:-}"
1012+
local new_list
1013+
[ -n "$ssid" ] || die_cli "用法: cli wifi del <SSID>"
1014+
new_list="$(wifi_list_del "$(read_conf "$TPROXY_CONF" "WIFI_SSID_LIST" "")" "$ssid")"
1015+
set_conf "$TPROXY_CONF" "WIFI_SSID_LIST" "$(quote_conf "$new_list")"
1016+
info "已移除 SSID: $ssid"
1017+
wifi_apply
1018+
}
1019+
1020+
# 列出名单
1021+
cmd_wifi_list() {
1022+
local list
1023+
list="$(read_conf "$TPROXY_CONF" "WIFI_SSID_LIST" "")"
1024+
if [ -z "$list" ]; then
1025+
printf "名单为空\n"
1026+
return 0
1027+
fi
1028+
printf "%s" "$list" | sed 's/,/,/g' | tr ',' '\n' | while IFS= read -r s; do
1029+
[ -n "$s" ] && printf " - %s\n" "$s"
1030+
done
1031+
}
1032+
1033+
# 清空名单
1034+
cmd_wifi_clear() {
1035+
set_conf "$TPROXY_CONF" "WIFI_SSID_LIST" "$(quote_conf "")"
1036+
info "名单已清空"
1037+
wifi_apply
1038+
}
1039+
1040+
# 设置非 WiFi 网络是否走代理。参数: $1 on/off
1041+
cmd_wifi_cellular() {
1042+
local value="${1:-}"
1043+
case "$value" in
1044+
on) set_conf "$TPROXY_CONF" "PROXY_ON_CELLULAR" "1" ;;
1045+
off) set_conf "$TPROXY_CONF" "PROXY_ON_CELLULAR" "0" ;;
1046+
*) die_cli "用法: cli wifi cellular <on|off>" ;;
1047+
esac
1048+
info "非 WiFi 网络代理已更新: $value"
1049+
wifi_apply
1050+
}
1051+
1052+
# wifi 命令组分发
1053+
cmd_wifi() {
1054+
local subcmd="${1:-status}"
1055+
shift 2> /dev/null || true
1056+
1057+
case "$subcmd" in
1058+
status) cmd_wifi_status "$@" ;;
1059+
on) cmd_wifi_on "$@" ;;
1060+
off) cmd_wifi_off "$@" ;;
1061+
mode) cmd_wifi_mode "$@" ;;
1062+
add) cmd_wifi_add "$@" ;;
1063+
del | remove | rm) cmd_wifi_del "$@" ;;
1064+
list) cmd_wifi_list "$@" ;;
1065+
clear) cmd_wifi_clear "$@" ;;
1066+
cellular) cmd_wifi_cellular "$@" ;;
1067+
help | -h | --help) show_wifi_help ;;
1068+
*) die_cli "用法错误,使用 cli wifi help 查看帮助" ;;
1069+
esac
1070+
}
1071+
1072+
8921073
# 显示全部命令组的总帮助
8931074
show_help() {
8941075
cat << EOF
@@ -944,6 +1125,14 @@ NetProxy CLI
9441125
cli tproxy reload 重载透明代理规则
9451126
cli tproxy quic <on|off> 开关 QUIC 阻断
9461127
cli tproxy cnip <on|off> 开关中国 IP 绕过
1128+
1129+
WiFi 自动切换:
1130+
cli wifi status 查看 WiFi 自动切换配置
1131+
cli wifi on | off 启用 / 禁用
1132+
cli wifi mode <blacklist|whitelist> 设置名单模式
1133+
cli wifi add <SSID> | del <SSID> 增删名单 SSID
1134+
cli wifi list | clear 列出 / 清空名单
1135+
cli wifi cellular <on|off> 非 WiFi 网络是否走代理
9471136
EOF
9481137
}
9491138

@@ -970,6 +1159,7 @@ main() {
9701159
api) cmd_api "$@" ;;
9711160
app) cmd_app "$@" ;;
9721161
tproxy) cmd_tproxy "$@" ;;
1162+
wifi) cmd_wifi "$@" ;;
9731163
help | -h | --help) show_help ;;
9741164
*) die_cli "未知命令组: $group,使用 cli help 查看帮助" ;;
9751165
esac

src/module/scripts/core/service.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ readonly CONFDIR="$SINGBOX_DIR/confdir" # 通用配置目录
2222
readonly RUNTIME_DIR="$SINGBOX_DIR/runtime" # 运行时生成目录
2323
readonly SWITCH_SCRIPT="$MODDIR/scripts/core/switch.sh" # 模式/节点切换脚本
2424
readonly TPROXY_SCRIPT="$MODDIR/scripts/network/tproxy.sh" # 透明代理脚本
25+
readonly NETMON_SCRIPT="$MODDIR/scripts/network/netmon.sh" # WiFi 自动切换监听脚本
2526
readonly KILL_TIMEOUT=5 # 等待进程退出的秒数上限
2627
readonly LOG_TAG="service" # 日志组件标签
2728

@@ -163,6 +164,8 @@ EOF
163164
if [ "$skip_tproxy" != "1" ]; then
164165
log "DEBUG" "正在加载透明代理规则..."
165166
"$TPROXY_SCRIPT" start -d "$TPROXY_CONF_DIR" >> "$LOG_FILE" 2>&1 || die "透明代理规则加载失败"
167+
# WiFi 自动切换:按配置启停监听守护并做初始决策 (失败不影响主流程)
168+
sh "$NETMON_SCRIPT" sync > /dev/null 2>&1 || log "WARN" "WiFi 自动切换初始化失败"
166169
fi
167170

168171
log "INFO" "sing-box 服务启动完成"
@@ -183,6 +186,8 @@ do_stop() {
183186

184187
# 先清理透明代理规则 (非跳过模式)
185188
if [ "$skip_tproxy" != "1" ]; then
189+
# 先停掉 WiFi 自动切换监听守护,避免其在清理期间误触发切换
190+
sh "$NETMON_SCRIPT" stop > /dev/null 2>&1 || true
186191
log "DEBUG" "正在清理透明代理规则..."
187192
"$TPROXY_SCRIPT" stop -d "$TPROXY_CONF_DIR" >> "$LOG_FILE" 2>&1 || true
188193
fi

0 commit comments

Comments
 (0)