mirror of
https://github.com/hotyue/IP-Sentinel.git
synced 2026-06-05 08:49:46 +08:00
恢复4.0.12版逻辑
This commit is contained in:
@@ -1,12 +1,8 @@
|
||||
#!/bin/bash
|
||||
|
||||
# ==========================================================
|
||||
# 脚本名称: mod_google.sh (V4.1.1 工业级行为学重构排雷版)
|
||||
# 核心功能:
|
||||
# 1. 数组级安全参数绑定 & curl 退出码精细捕获
|
||||
# 2. UA 平台分离,构建平台专属行为矩阵
|
||||
# 3. 引入 70% 概率动态 Referer 链 (业务域物理隔离)
|
||||
# 4. 符合泊松分布(Poisson)的非均匀真实人类阅读停留时长
|
||||
# 脚本名称: mod_google.sh (Google 业务逻辑模块 - 动态锚点版)
|
||||
# 核心功能: 执行坐标微抖动、模拟真实阅读时长、会话行为拉伸
|
||||
# ==========================================================
|
||||
|
||||
MODULE_NAME="Google"
|
||||
@@ -20,13 +16,10 @@ else
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# [V4.1.1 修复] 环境变量兜底保护,防配置丢失导致 URL 畸形
|
||||
GOOGLE_BASE_URL="${GOOGLE_BASE_URL:-https://www.google.com}"
|
||||
|
||||
# 容错机制:如果父进程没有传递 log 函数,则本地定义一个作为 fallback
|
||||
# 容错机制:如果父进程没有传递 log 函数,则本地定义一个作为 fallback (v3.4.0 引入版本探针)
|
||||
if ! type log >/dev/null 2>&1; then
|
||||
log() {
|
||||
# 提取当前配置中的版本锚点
|
||||
# [v3.4.0 核心] 提取当前配置中的版本锚点
|
||||
local local_ver="${AGENT_VERSION:-未知}"
|
||||
|
||||
# 保证日志目录存在
|
||||
@@ -37,10 +30,11 @@ if ! type log >/dev/null 2>&1; then
|
||||
# [时区对齐] 强制无视本地时区,以绝对 UTC 时间写入日志
|
||||
echo "[$(date -u '+%Y-%m-%d %H:%M:%S UTC')] $core_msg" >> "${INSTALL_DIR}/logs/sentinel.log"
|
||||
|
||||
# 强制推送到 Systemd Journal
|
||||
# 强制推送到 Systemd Journal (如果系统支持)
|
||||
if command -v logger >/dev/null 2>&1; then
|
||||
logger -t ip-sentinel "$core_msg"
|
||||
else
|
||||
# 降级输出到 stdout,让 Systemd 捕获
|
||||
echo "$core_msg"
|
||||
fi
|
||||
}
|
||||
@@ -48,16 +42,6 @@ fi
|
||||
|
||||
log "$MODULE_NAME" "START" "========== 唤醒网络模拟器 [区域: $REGION_NAME] =========="
|
||||
|
||||
# --- [V4.1.1 强制依赖检测 (防系统环境残缺)] ---
|
||||
MISSING_DEPS=()
|
||||
for dep in jq curl awk flock; do
|
||||
command -v "$dep" >/dev/null 2>&1 || MISSING_DEPS+=("$dep")
|
||||
done
|
||||
if [ ${#MISSING_DEPS[@]} -gt 0 ]; then
|
||||
log "$MODULE_NAME" "ERROR" "系统残缺,缺少必备组件: ${MISSING_DEPS[*]}。拒绝执行。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 2. 动态加载热数据 (设备指纹池 和 专属搜索词库)
|
||||
UA_FILE="${INSTALL_DIR}/data/user_agents.txt"
|
||||
KW_FILE="${INSTALL_DIR}/data/keywords/kw_${REGION_CODE}.txt"
|
||||
@@ -71,11 +55,6 @@ fi
|
||||
mapfile -t UA_POOL < <(grep -v '^$' "$UA_FILE")
|
||||
mapfile -t KEYWORDS < <(grep -v '^$' "$KW_FILE")
|
||||
|
||||
if [ ${#KEYWORDS[@]} -eq 0 ]; then
|
||||
log "$MODULE_NAME" "ERROR" "关键词库为空,终止执行。"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# --- [工具函数] ---
|
||||
get_random_coord() {
|
||||
local base=$1
|
||||
@@ -85,6 +64,7 @@ get_random_coord() {
|
||||
}
|
||||
|
||||
# --- [环境初始化] ---
|
||||
# [v3.3.1修改] 优先读取对外公网面孔作为哈希种子,兼容 NAT 机的空 BIND_IP
|
||||
CURRENT_IP="${PUBLIC_IP:-${BIND_IP:-Unknown}}"
|
||||
|
||||
# -----------------------------------------------------------
|
||||
@@ -93,322 +73,150 @@ CURRENT_IP="${PUBLIC_IP:-${BIND_IP:-Unknown}}"
|
||||
# -----------------------------------------------------------
|
||||
TOTAL_UA=${#UA_POOL[@]}
|
||||
if [ "$TOTAL_UA" -gt 0 ]; then
|
||||
# 1. 以本地锁定的公网 IP 为种子,计算固定不变的 CRC32 哈希值
|
||||
SEED=$(echo -n "$CURRENT_IP" | cksum | awk '{print $1}')
|
||||
|
||||
# 2. 利用确定的种子和质数乘数,在全球 4000 的库中计算出本机的 3 个绝对专属坐标
|
||||
IDX1=$(( SEED % TOTAL_UA ))
|
||||
IDX2=$(( (SEED * 17) % TOTAL_UA ))
|
||||
IDX3=$(( (SEED * 31) % TOTAL_UA ))
|
||||
|
||||
# 3. 将绝对坐标映射为该节点的“专属设备库”
|
||||
MY_UA_POOL=("${UA_POOL[$IDX1]}" "${UA_POOL[$IDX2]}" "${UA_POOL[$IDX3]}")
|
||||
|
||||
# 4. 本次会话从这 3 台专属设备中随机挑选 1 台进行模拟
|
||||
SESSION_UA=${MY_UA_POOL[$RANDOM % 3]}
|
||||
else
|
||||
SESSION_UA="Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0"
|
||||
# 兜底容错机制
|
||||
SESSION_UA="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0.0.0 Safari/537.36"
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# [V4.1.1 平台身份提取器 (Persona Mapper)]
|
||||
# -----------------------------------------------------------
|
||||
UA_PLATFORM="windows"
|
||||
if [[ "$SESSION_UA" == *"Android"* ]]; then
|
||||
UA_PLATFORM="android"
|
||||
elif [[ "$SESSION_UA" == *"iPhone"* ]] || [[ "$SESSION_UA" == *"iPad"* ]]; then
|
||||
UA_PLATFORM="ios"
|
||||
elif [[ "$SESSION_UA" == *"Macintosh"* ]]; then
|
||||
UA_PLATFORM="macos"
|
||||
elif [[ "$SESSION_UA" == *"Linux"* ]]; then
|
||||
UA_PLATFORM="linux"
|
||||
fi
|
||||
|
||||
# 位置锁定:在基准点(比如东京新宿)附近 3 公里内随机生成本次上网的“固定咖啡馆”坐标
|
||||
SESSION_BASE_LAT=$(get_random_coord $BASE_LAT 270)
|
||||
SESSION_BASE_LON=$(get_random_coord $BASE_LON 270)
|
||||
|
||||
# 【核心升级】随机决定本次上网深度 (5 - 8 个复合动作,配合高频长效拉伸)
|
||||
TOTAL_ACTIONS=$((5 + RANDOM % 4))
|
||||
|
||||
log "$MODULE_NAME" "INFO " "指纹锁定: ${SESSION_UA:0:45}..."
|
||||
log "$MODULE_NAME" "INFO " "平台推断: [$UA_PLATFORM] | 驻留坐标: $SESSION_BASE_LAT, $SESSION_BASE_LON"
|
||||
log "$MODULE_NAME" "INFO " "当前出网 IP: $CURRENT_IP"
|
||||
log "$MODULE_NAME" "INFO " "设备指纹锁定: ${SESSION_UA:0:45}..."
|
||||
log "$MODULE_NAME" "INFO " "虚拟驻留坐标: $SESSION_BASE_LAT, $SESSION_BASE_LON"
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# [V4.1.1] 持久化 Cookie 身份库
|
||||
# [V3.2.1 热修复] 网络锚定与协议自适应构建
|
||||
# 强制 curl 绑定网卡,并自动匹配 IPv4/v6 协议,杜绝 curl 冲突报错
|
||||
# -----------------------------------------------------------
|
||||
COOKIE_DIR="${INSTALL_DIR}/data/cookies"
|
||||
mkdir -p "$COOKIE_DIR"
|
||||
NODE_HASH=$(echo -n "$CURRENT_IP" | cksum | awk '{print $1}')
|
||||
COOKIE_FILE="${COOKIE_DIR}/google_${NODE_HASH}.txt"
|
||||
|
||||
LOCK_FILE="${COOKIE_FILE}.lock"
|
||||
exec 200>"$LOCK_FILE"
|
||||
flock -n 200 || {
|
||||
log "$MODULE_NAME" "WARN " "检测到已有 Google 会话运行,跳过本轮。"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# [V4.1.1 数组级安全参数绑定]
|
||||
# 彻底消除 Shell Word Splitting(拆词)风险
|
||||
# -----------------------------------------------------------
|
||||
CURL_BIND_OPT=()
|
||||
DYNAMIC_IP_PREF="-${IP_PREF:-4}"
|
||||
CURL_BIND_OPT=""
|
||||
DYNAMIC_IP_PREF="-${IP_PREF:-4}" # 默认提取用户配置
|
||||
|
||||
if [[ -n "$BIND_IP" && "$BIND_IP" =~ ^[0-9a-fA-F:\.]+$ ]]; then
|
||||
# [v3.6.3 容错层补丁] 探测物理网卡/虚拟 IP 存活状态
|
||||
RAW_BIND_IP=$(echo "$BIND_IP" | tr -d '[]')
|
||||
if ! ip addr show 2>/dev/null | grep -Fq "$RAW_BIND_IP"; then
|
||||
if ! ip addr show 2>/dev/null | grep -qw "$RAW_BIND_IP"; then
|
||||
log "$MODULE_NAME" "WARN " "检测到配置的出口 IP ($RAW_BIND_IP) 已丢失,自动降级为系统默认路由出网!"
|
||||
CURL_BIND_OPT=""
|
||||
else
|
||||
CURL_BIND_OPT+=(--interface "$BIND_IP")
|
||||
CURL_BIND_OPT="--interface $BIND_IP"
|
||||
# 智能探测:带冒号为 V6,带点号为 V4
|
||||
if [[ "$BIND_IP" == *":"* ]]; then
|
||||
DYNAMIC_IP_PREF="-6"
|
||||
log "$MODULE_NAME" "INFO " "底层路由锁定: 绑定 IPv6 出口及协议 ($BIND_IP)"
|
||||
elif [[ "$BIND_IP" == *"."* ]]; then
|
||||
DYNAMIC_IP_PREF="-4"
|
||||
log "$MODULE_NAME" "INFO " "底层路由锁定: 绑定 IPv4 出口及协议 ($BIND_IP)"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
|
||||
# -----------------------------------------------------------
|
||||
# [V4.1.1] 生物节律系统
|
||||
# -----------------------------------------------------------
|
||||
LOCAL_HOUR=$(date +%H)
|
||||
if [ "$LOCAL_HOUR" -ge 1 ] && [ "$LOCAL_HOUR" -le 6 ]; then
|
||||
if [ $((RANDOM % 100)) -lt 70 ]; then
|
||||
log "$MODULE_NAME" "INFO " "🌙 夜间生物节律触发,本轮进入深度睡眠。"
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
# ==========================================================
|
||||
# [V4.1.1] 底层静态 Curl 参数提取 (剥离 -f 陷阱)
|
||||
# 抛弃 -f (fail silently) 才能精准捕获 HTTP 403 / 429 风控拦截
|
||||
# ==========================================================
|
||||
BASE_CURL=(curl -sSL --connect-timeout 10 -m 25)
|
||||
BASE_CURL+=("$DYNAMIC_IP_PREF")
|
||||
BASE_CURL+=(--http2)
|
||||
if [ ${#CURL_BIND_OPT[@]} -gt 0 ]; then
|
||||
BASE_CURL+=("${CURL_BIND_OPT[@]}")
|
||||
fi
|
||||
BASE_CURL+=(-b "$COOKIE_FILE" -c "$COOKIE_FILE")
|
||||
BASE_CURL+=(-A "$SESSION_UA")
|
||||
BASE_CURL+=(-H "Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8")
|
||||
BASE_CURL+=(-H "Accept-Language: ${LANG_ACCEPT}")
|
||||
BASE_CURL+=(-H "Upgrade-Insecure-Requests: 1")
|
||||
BASE_CURL+=(-H "DNT: 1")
|
||||
if [ -n "$GEO_HEADER" ]; then
|
||||
BASE_CURL+=(-H "$GEO_HEADER")
|
||||
fi
|
||||
|
||||
# [V4.1.1] 业务域 Referer 物理隔离 (防穿帮)
|
||||
REF_SEARCH=""
|
||||
REF_NEWS=""
|
||||
REF_MAPS=""
|
||||
REF_ECO=""
|
||||
|
||||
LOW_RISK_ECO=(
|
||||
"https://about.google/"
|
||||
"https://safety.google/"
|
||||
"https://policies.google.com/privacy?hl=${LANG_ACCEPT%%,*}"
|
||||
"https://support.google.com/?hl=${LANG_ACCEPT%%,*}"
|
||||
)
|
||||
|
||||
# --- [行为循环模拟] ---
|
||||
for ((i=1; i<=TOTAL_ACTIONS; i++)); do
|
||||
# 模拟真实移动设备拿在手里时的 GPS 信号微抖动 (范围约 10 米)
|
||||
ACTION_LAT=$(get_random_coord $SESSION_BASE_LAT 1)
|
||||
ACTION_LON=$(get_random_coord $SESSION_BASE_LON 1)
|
||||
|
||||
# 随机抽取一个符合当地特征的热点搜索词
|
||||
RAND_KEY=${KEYWORDS[$RANDOM % ${#KEYWORDS[@]}]}
|
||||
ENCODED_KEY=$(echo "$RAND_KEY" | jq -sRr @uri)
|
||||
|
||||
# [V4.1.1 修复] 切回最可靠的原生 jq uri,完美支持 UTF-8 中文编码
|
||||
ENCODED_KEY=$(printf '%s' "$RAND_KEY" | jq -sRr @uri)
|
||||
[ -z "$ENCODED_KEY" ] && ENCODED_KEY="google"
|
||||
|
||||
ACTION_DICE=$((RANDOM % 100))
|
||||
TARGET_URL=""
|
||||
ACTION_LOG=""
|
||||
|
||||
# [V4.1.1] 基于平台的动态行为矩阵选择 (杜绝 iOS 访问 Android 探针)
|
||||
if [ "$UA_PLATFORM" == "android" ]; then
|
||||
if [ $ACTION_DICE -lt 25 ]; then
|
||||
TARGET_URL="${GOOGLE_BASE_URL}/search?q=${ENCODED_KEY}&${LANG_PARAMS}"
|
||||
ACTION_LOG="Search "
|
||||
elif [ $ACTION_DICE -lt 55 ]; then
|
||||
TARGET_URL="https://news.google.com/home?${LANG_PARAMS}"
|
||||
ACTION_LOG="News "
|
||||
elif [ $ACTION_DICE -lt 85 ]; then
|
||||
TARGET_URL="https://www.google.com/maps?q=${ENCODED_KEY}&ll=${ACTION_LAT},${ACTION_LON}&z=17"
|
||||
ACTION_LOG="Maps "
|
||||
else
|
||||
TARGET_URL="https://connectivitycheck.gstatic.com/generate_204"
|
||||
ACTION_LOG="NetTest"
|
||||
fi
|
||||
elif [ "$UA_PLATFORM" == "ios" ] || [ "$UA_PLATFORM" == "macos" ]; then
|
||||
if [ $ACTION_DICE -lt 30 ]; then
|
||||
TARGET_URL="${GOOGLE_BASE_URL}/search?q=${ENCODED_KEY}&${LANG_PARAMS}"
|
||||
ACTION_LOG="Search "
|
||||
elif [ $ACTION_DICE -lt 65 ]; then
|
||||
TARGET_URL="https://news.google.com/home?${LANG_PARAMS}"
|
||||
ACTION_LOG="News "
|
||||
elif [ $ACTION_DICE -lt 90 ]; then
|
||||
TARGET_URL="https://www.google.com/maps?q=${ENCODED_KEY}&ll=${ACTION_LAT},${ACTION_LON}&z=17"
|
||||
ACTION_LOG="Maps "
|
||||
else
|
||||
TARGET_URL="https://captive.apple.com/hotspot-detect.html"
|
||||
ACTION_LOG="NetTest"
|
||||
fi
|
||||
else
|
||||
# Windows / Linux 专属行为矩阵
|
||||
if [ $ACTION_DICE -lt 20 ]; then
|
||||
TARGET_URL="${GOOGLE_BASE_URL}/search?q=${ENCODED_KEY}&${LANG_PARAMS}"
|
||||
ACTION_LOG="Search "
|
||||
elif [ $ACTION_DICE -lt 60 ]; then
|
||||
TARGET_URL="https://news.google.com/home?${LANG_PARAMS}"
|
||||
ACTION_LOG="News "
|
||||
elif [ $ACTION_DICE -lt 80 ]; then
|
||||
TARGET_URL="${LOW_RISK_ECO[$((RANDOM % ${#LOW_RISK_ECO[@]}))]}"
|
||||
ACTION_LOG="EcoRoam"
|
||||
else
|
||||
TARGET_URL="https://www.google.com/maps?q=${ENCODED_KEY}&ll=${ACTION_LAT},${ACTION_LON}&z=17"
|
||||
ACTION_LOG="Maps "
|
||||
fi
|
||||
fi
|
||||
|
||||
# [V4.1.1] Referer 业务域隔离判断
|
||||
CTX_REF=""
|
||||
case "$ACTION_LOG" in
|
||||
"Search "*) CTX_REF="$REF_SEARCH" ;;
|
||||
"News "*) CTX_REF="$REF_NEWS" ;;
|
||||
"Maps "*) CTX_REF="$REF_MAPS" ;;
|
||||
"EcoRoam"*) CTX_REF="$REF_ECO" ;;
|
||||
# 随机选择一种上网行为
|
||||
ACTION_TYPE=$((1 + RANDOM % 4))
|
||||
|
||||
# [V3.2.1 热修复] 注入 $CURL_BIND_OPT 与 $DYNAMIC_IP_PREF 协议自适应
|
||||
case $ACTION_TYPE in
|
||||
1) # 搜索行为
|
||||
CODE=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 15 -s -L -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
|
||||
"https://www.google.com/search?q=${ENCODED_KEY}&${LANG_PARAMS}")
|
||||
;;
|
||||
2) # 浏览本土新闻
|
||||
CODE=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 15 -s -L -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
|
||||
"https://news.google.com/home?${LANG_PARAMS}")
|
||||
;;
|
||||
3) # 地图坐标查询
|
||||
CODE=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 15 -s -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
|
||||
"https://www.google.com/maps/search/$${ENCODED_KEY}/@${ACTION_LAT},${ACTION_LON},17z?${LANG_PARAMS}")
|
||||
;;
|
||||
4) # 触发移动端系统底层位置检测像素
|
||||
CODE=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 10 -s -o /dev/null -w "%{http_code}" -A "$SESSION_UA" \
|
||||
"https://connectivitycheck.gstatic.com/generate_204")
|
||||
;;
|
||||
esac
|
||||
|
||||
# 动态载入 Referer (70% 概率)
|
||||
CURL_EXEC=("${BASE_CURL[@]}")
|
||||
if [ -n "$CTX_REF" ] && [ $((RANDOM % 100)) -lt 70 ]; then
|
||||
CURL_EXEC+=(-H "Referer: $CTX_REF")
|
||||
fi
|
||||
|
||||
# 执行命令并捕获细分错误码
|
||||
HTTP_CODE=$("${CURL_EXEC[@]}" -o /dev/null -w "%{http_code}" "$TARGET_URL")
|
||||
CURL_EXIT=$?
|
||||
|
||||
# [V4.1.1] 精确分离 Curl 网络错误与 HTTP 协议层拦截
|
||||
if [ $CURL_EXIT -ne 0 ]; then
|
||||
case $CURL_EXIT in
|
||||
6) CURL_ERR_CODE="ERR_6_DNS" ;;
|
||||
7) CURL_ERR_CODE="ERR_7_CONN" ;;
|
||||
28) CURL_ERR_CODE="ERR_28_TIMEOUT" ;;
|
||||
35) CURL_ERR_CODE="ERR_35_TLS" ;;
|
||||
56) CURL_ERR_CODE="ERR_56_RESET" ;;
|
||||
*) CURL_ERR_CODE="ERR_${CURL_EXIT}" ;;
|
||||
esac
|
||||
log "$MODULE_NAME" "WARN " "❌ ${ACTION_LOG} Curl底层故障 | Code: $CURL_ERR_CODE | T: ${TARGET_URL:0:35}"
|
||||
|
||||
# 请求失败,清空当前业务链的 Referer
|
||||
case "$ACTION_LOG" in
|
||||
"Search "*) REF_SEARCH="" ;;
|
||||
"News "*) REF_NEWS="" ;;
|
||||
"Maps "*) REF_MAPS="" ;;
|
||||
"EcoRoam"*) REF_ECO="" ;;
|
||||
esac
|
||||
else
|
||||
# Curl 连通了,评估 HTTP 状态码
|
||||
if [[ "$HTTP_CODE" =~ ^[23] ]]; then
|
||||
log "$MODULE_NAME" "EXEC " "✅ ${ACTION_LOG} success | Code: $HTTP_CODE | T: ${TARGET_URL:0:35}"
|
||||
# 更新业务专属跳板 (网络测试页不作为 Referer)
|
||||
case "$ACTION_LOG" in
|
||||
"Search "*) REF_SEARCH="$TARGET_URL" ;;
|
||||
"News "*) REF_NEWS="$TARGET_URL" ;;
|
||||
"Maps "*) REF_MAPS="$TARGET_URL" ;;
|
||||
"EcoRoam"*) REF_ECO="$TARGET_URL" ;;
|
||||
esac
|
||||
else
|
||||
log "$MODULE_NAME" "WARN " "❌ ${ACTION_LOG} 疑似遭风控拒绝 | Code: $HTTP_CODE | T: ${TARGET_URL:0:35}"
|
||||
fi
|
||||
fi
|
||||
|
||||
# [V4.1.1] 泊松长尾分布,模拟人类真实停留
|
||||
log "$MODULE_NAME" "EXEC " "动作[$i/$TOTAL_ACTIONS]完成 | HTTP状态: $CODE | 抖动坐标: $ACTION_LAT, $ACTION_LON"
|
||||
|
||||
# 【核心升级】行为拉伸:每次动作后强制休眠 90 - 120 秒
|
||||
# 结合动作总数,总耗时将稳定在 10 分钟 到 20 分钟之间
|
||||
if [ $i -lt $TOTAL_ACTIONS ]; then
|
||||
SLEEP_DICE=$((RANDOM % 100))
|
||||
if [ $SLEEP_DICE -lt 45 ]; then
|
||||
SLEEP_TIME=$((8 + RANDOM % 13)) # 8 - 20s (45%)
|
||||
elif [ $SLEEP_DICE -lt 80 ]; then
|
||||
SLEEP_TIME=$((20 + RANDOM % 41)) # 20 - 60s (35%)
|
||||
elif [ $SLEEP_DICE -lt 95 ]; then
|
||||
SLEEP_TIME=$((60 + RANDOM % 121)) # 60 - 180s (15%)
|
||||
else
|
||||
SLEEP_TIME=$((180 + RANDOM % 300)) # 180 - 480s (5%)
|
||||
fi
|
||||
log "$MODULE_NAME" "WAIT " "模拟真实浏览,停留 ${SLEEP_TIME}s..."
|
||||
# 【时间收敛修复】休眠控制在 45-75 秒,防止跨周期重叠导致进程被强杀
|
||||
SLEEP_TIME=$((45 + RANDOM % 31))
|
||||
log "$MODULE_NAME" "WAIT " "阅读当前页面内容,模拟停留 $SLEEP_TIME 秒..."
|
||||
sleep $SLEEP_TIME
|
||||
fi
|
||||
done
|
||||
|
||||
# ==========================================================
|
||||
# Google / YouTube 区域判定逻辑
|
||||
# 三核探针:
|
||||
# 1. Google 跳转域
|
||||
# 2. YouTube Premium
|
||||
# 3. YouTube Music
|
||||
# ==========================================================
|
||||
# --- [结果纠偏自检 (V4.0.9 终极三核雷达: URL跳转 + Premium + Music)] ---
|
||||
# 战术揭秘:汲取开源社区顶级探针的精髓!
|
||||
# 1. 传统 URL 跳转探测:捕捉 www.google.com 底层 302 重定向域名的真实归属。
|
||||
# 2. YT Premium 深度探测:提取核心 contentRegion 变量,并强匹配 www.google.cn 送中特征。
|
||||
# 3. 严格一致性校验:任何一端出现非预期偏移,立即判定为漂移,彻底消除虚假“成功”。
|
||||
|
||||
log "$MODULE_NAME" "INFO " "启动三核交叉验证 (URL跳转 + YT Premium + YT Music) 穿透获取 GeoIP..."
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 核心 1: Google 跳转探针
|
||||
# ----------------------------------------------------------
|
||||
JUMP_HDR=$(curl -sI -m 10 --http2 \
|
||||
$DYNAMIC_IP_PREF \
|
||||
${CURL_BIND_OPT[@]:+"${CURL_BIND_OPT[@]}"} \
|
||||
-b "$COOKIE_FILE" -c "$COOKIE_FILE" \
|
||||
-A "$SESSION_UA" \
|
||||
-H "Accept-Language: ${LANG_ACCEPT}" \
|
||||
"http://www.google.com/")
|
||||
|
||||
# 核心 1: 传统 URL 跳转探测 (请求 www 才能触发准确跳转)
|
||||
JUMP_HDR=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 10 -sI "http://www.google.com/")
|
||||
JUMP_LOC=$(echo "$JUMP_HDR" | grep -i "^location:" | tr -d '\r\n')
|
||||
JUMP_GL=""
|
||||
|
||||
if [ -z "$JUMP_LOC" ]; then
|
||||
# 没跳转,默认 Google 原生 US
|
||||
# 无跳转 (HTTP 200) 通常意味着原生被定位于 US
|
||||
JUMP_GL="US"
|
||||
|
||||
elif [[ "$JUMP_LOC" == *".google.cn"* ]] || [[ "$JUMP_LOC" == *"gl=CN"* ]]; then
|
||||
# 明确送中
|
||||
JUMP_GL="CN"
|
||||
|
||||
elif [[ "$JUMP_LOC" == *"gl="* ]]; then
|
||||
# URL 参数直接带 gl=
|
||||
JUMP_GL=$(echo "$JUMP_LOC" \
|
||||
| grep -o 'gl=[A-Za-z]\{2\}' \
|
||||
| head -n 1 \
|
||||
| cut -d'=' -f2 \
|
||||
| tr 'a-z' 'A-Z')
|
||||
|
||||
JUMP_GL=$(echo "$JUMP_LOC" | grep -o 'gl=[A-Za-z]\{2\}' | head -n 1 | cut -d'=' -f2 | tr 'a-z' 'A-Z')
|
||||
else
|
||||
# 域名后缀解析
|
||||
JUMP_DOMAIN=$(echo "$JUMP_LOC" \
|
||||
| grep -o 'google\.[a-z\.]*' \
|
||||
| head -n 1 \
|
||||
| sed 's/google\.//')
|
||||
|
||||
# 从域名中提取区域后缀 (如 .co.jp -> JP, .com.hk -> HK, .de -> DE)
|
||||
JUMP_DOMAIN=$(echo "$JUMP_LOC" | grep -o 'google\.[a-z\.]*' | head -n 1 | sed 's/google\.//')
|
||||
case "$JUMP_DOMAIN" in
|
||||
"com") JUMP_GL="US" ;;
|
||||
"com") JUMP_GL="US" ;;
|
||||
"com.hk") JUMP_GL="HK" ;;
|
||||
"com.tw") JUMP_GL="TW" ;;
|
||||
"co.jp") JUMP_GL="JP" ;;
|
||||
"co.uk") JUMP_GL="GB" ;;
|
||||
"co.kr") JUMP_GL="KR" ;;
|
||||
"co.in") JUMP_GL="IN" ;;
|
||||
"co.id") JUMP_GL="ID" ;;
|
||||
"co.th") JUMP_GL="TH" ;;
|
||||
"co.jp") JUMP_GL="JP" ;;
|
||||
"co.uk") JUMP_GL="GB" ;;
|
||||
"co.kr") JUMP_GL="KR" ;;
|
||||
"co.in") JUMP_GL="IN" ;;
|
||||
"co.id") JUMP_GL="ID" ;;
|
||||
"co.th") JUMP_GL="TH" ;;
|
||||
"com.sg") JUMP_GL="SG" ;;
|
||||
"com.my") JUMP_GL="MY" ;;
|
||||
"com.au") JUMP_GL="AU" ;;
|
||||
"com.br") JUMP_GL="BR" ;;
|
||||
"com.mx") JUMP_GL="MX" ;;
|
||||
"com.ar") JUMP_GL="AR" ;;
|
||||
"co.za") JUMP_GL="ZA" ;;
|
||||
"cn") JUMP_GL="CN" ;;
|
||||
"")
|
||||
JUMP_GL=""
|
||||
;;
|
||||
*)
|
||||
LAST_EXT=$(echo "$JUMP_DOMAIN" \
|
||||
| awk -F'.' '{print $NF}' \
|
||||
| tr 'a-z' 'A-Z')
|
||||
|
||||
"co.za") JUMP_GL="ZA" ;;
|
||||
"cn") JUMP_GL="CN" ;;
|
||||
"") JUMP_GL="" ;;
|
||||
*)
|
||||
# 提取标准两字母后缀 (.de, .fr, .nl)
|
||||
LAST_EXT=$(echo "$JUMP_DOMAIN" | awk -F'.' '{print $NF}' | tr 'a-z' 'A-Z')
|
||||
if [ ${#LAST_EXT} -eq 2 ]; then
|
||||
JUMP_GL="$LAST_EXT"
|
||||
else
|
||||
@@ -418,168 +226,72 @@ else
|
||||
esac
|
||||
fi
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 核心 2: YouTube Premium 探针
|
||||
# ----------------------------------------------------------
|
||||
# 核心 2: YouTube Premium 探测
|
||||
YT_PR_GL=""
|
||||
|
||||
YT_PR_HTML=$(curl -sSL -m 10 --http2 \
|
||||
$DYNAMIC_IP_PREF \
|
||||
${CURL_BIND_OPT[@]:+"${CURL_BIND_OPT[@]}"} \
|
||||
-b "$COOKIE_FILE" -c "$COOKIE_FILE" \
|
||||
-A "$SESSION_UA" \
|
||||
-H "Accept-Language: ${LANG_ACCEPT}" \
|
||||
"https://www.youtube.com/premium")
|
||||
|
||||
# [修复] 必须带上本轮循环的专属 UA (-A "$SESSION_UA"),防止被 Google CDN 丢进无状态爬虫兜底页
|
||||
YT_PR_HTML=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 10 -s -L -A "$SESSION_UA" "https://www.youtube.com/premium")
|
||||
if [[ "$YT_PR_HTML" == *"www.google.cn"* ]]; then
|
||||
|
||||
YT_PR_GL="CN"
|
||||
|
||||
else
|
||||
|
||||
YT_PR_GL=$(echo "$YT_PR_HTML" \
|
||||
| grep -o '"contentRegion":"[A-Za-z]\{2\}"' \
|
||||
| head -n 1 \
|
||||
| cut -d'"' -f4 \
|
||||
| tr 'a-z' 'A-Z')
|
||||
|
||||
[ -z "$YT_PR_GL" ] && \
|
||||
YT_PR_GL=$(echo "$YT_PR_HTML" \
|
||||
| grep -o '"countryCode":"[A-Za-z]\{2\}"' \
|
||||
| head -n 1 \
|
||||
| cut -d'"' -f4 \
|
||||
| tr 'a-z' 'A-Z')
|
||||
|
||||
[ -z "$YT_PR_GL" ] && \
|
||||
YT_PR_GL=$(echo "$YT_PR_HTML" \
|
||||
| grep -o '"INNERTUBE_CONTEXT_GL":"[A-Za-z]\{2\}"' \
|
||||
| head -n 1 \
|
||||
| cut -d'"' -f4 \
|
||||
| tr 'a-z' 'A-Z')
|
||||
# 穷举风控变量提取
|
||||
YT_PR_GL=$(echo "$YT_PR_HTML" | grep -o '"contentRegion":"[A-Za-z]\{2\}"' | head -n 1 | cut -d'"' -f4 | tr 'a-z' 'A-Z')
|
||||
[ -z "$YT_PR_GL" ] && YT_PR_GL=$(echo "$YT_PR_HTML" | grep -o '"countryCode":"[A-Za-z]\{2\}"' | head -n 1 | cut -d'"' -f4 | tr 'a-z' 'A-Z')
|
||||
[ -z "$YT_PR_GL" ] && YT_PR_GL=$(echo "$YT_PR_HTML" | grep -o '"INNERTUBE_CONTEXT_GL":"[A-Za-z]\{2\}"' | head -n 1 | cut -d'"' -f4 | tr 'a-z' 'A-Z')
|
||||
fi
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 核心 3: YouTube Music 探针
|
||||
# ----------------------------------------------------------
|
||||
# 核心 3: YouTube Music 探测
|
||||
YT_MU_GL=""
|
||||
|
||||
YT_MU_HTML=$(curl -sSL -m 10 --http2 \
|
||||
$DYNAMIC_IP_PREF \
|
||||
${CURL_BIND_OPT[@]:+"${CURL_BIND_OPT[@]}"} \
|
||||
-b "$COOKIE_FILE" -c "$COOKIE_FILE" \
|
||||
-A "$SESSION_UA" \
|
||||
-H "Accept-Language: ${LANG_ACCEPT}" \
|
||||
"https://music.youtube.com/")
|
||||
|
||||
# [修复] 同样加持 UA 装甲,强行唤出完整版前端框架
|
||||
YT_MU_HTML=$(curl $CURL_BIND_OPT $DYNAMIC_IP_PREF -m 10 -s -L -A "$SESSION_UA" "https://music.youtube.com/")
|
||||
if [[ "$YT_MU_HTML" == *"www.google.cn"* ]]; then
|
||||
|
||||
YT_MU_GL="CN"
|
||||
|
||||
else
|
||||
|
||||
YT_MU_GL=$(echo "$YT_MU_HTML" \
|
||||
| grep -o '"INNERTUBE_CONTEXT_GL":"[A-Za-z]\{2\}"' \
|
||||
| head -n 1 \
|
||||
| cut -d'"' -f4 \
|
||||
| tr 'a-z' 'A-Z')
|
||||
|
||||
[ -z "$YT_MU_GL" ] && \
|
||||
YT_MU_GL=$(echo "$YT_MU_HTML" \
|
||||
| grep -o '"countryCode":"[A-Za-z]\{2\}"' \
|
||||
| head -n 1 \
|
||||
| cut -d'"' -f4 \
|
||||
| tr 'a-z' 'A-Z')
|
||||
|
||||
[ -z "$YT_MU_GL" ] && \
|
||||
YT_MU_GL=$(echo "$YT_MU_HTML" \
|
||||
| grep -o '"GL":"[A-Za-z]\{2\}"' \
|
||||
| head -n 1 \
|
||||
| cut -d'"' -f4 \
|
||||
| tr 'a-z' 'A-Z')
|
||||
# [修复] Music 的核心配置变量是 INNERTUBE_CONTEXT_GL
|
||||
YT_MU_GL=$(echo "$YT_MU_HTML" | grep -o '"INNERTUBE_CONTEXT_GL":"[A-Za-z]\{2\}"' | head -n 1 | cut -d'"' -f4 | tr 'a-z' 'A-Z')
|
||||
[ -z "$YT_MU_GL" ] && YT_MU_GL=$(echo "$YT_MU_HTML" | grep -o '"countryCode":"[A-Za-z]\{2\}"' | head -n 1 | cut -d'"' -f4 | tr 'a-z' 'A-Z')
|
||||
[ -z "$YT_MU_GL" ] && YT_MU_GL=$(echo "$YT_MU_HTML" | grep -o '"GL":"[A-Za-z]\{2\}"' | head -n 1 | cut -d'"' -f4 | tr 'a-z' 'A-Z')
|
||||
fi
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 目标区域标准化
|
||||
# ----------------------------------------------------------
|
||||
# [基准对齐] 提取配置大区 (兼容州级穿透),并修正英国的 ISO 代码
|
||||
TARGET_CC="${REGION_CODE%%-*}"
|
||||
|
||||
# 英国 ISO 特判
|
||||
[ "$TARGET_CC" == "UK" ] && TARGET_CC="GB"
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 终极审判逻辑
|
||||
# ----------------------------------------------------------
|
||||
# --- 终极审判逻辑 (以 YouTube 核心业务为主导,兼顾底层雷达权重) ---
|
||||
IS_CN=0
|
||||
VALID_PROBES=0
|
||||
|
||||
# 1. 扫描所有探针,统计有效性并执行“送中”一票否决
|
||||
for val in "$JUMP_GL" "$YT_PR_GL" "$YT_MU_GL"; do
|
||||
if [ -n "$val" ]; then
|
||||
((VALID_PROBES++))
|
||||
|
||||
# 任意探针命中 CN -> 一票否决
|
||||
[ "$val" == "CN" ] && IS_CN=1
|
||||
fi
|
||||
done
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 三核全部失效
|
||||
# ----------------------------------------------------------
|
||||
if [ $VALID_PROBES -eq 0 ]; then
|
||||
|
||||
STATUS="🚨 探针失效 (三核全部熔断,可能遭严重风控拦截)"
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 送中判定
|
||||
# ----------------------------------------------------------
|
||||
elif [ $IS_CN -eq 1 ]; then
|
||||
|
||||
STATUS="❌ 严重高危!三核雷达判定 IP 已被中国大陆锁定 (送中)!"
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 非送中 -> 判断是否区域达标
|
||||
# ----------------------------------------------------------
|
||||
else
|
||||
|
||||
# 2. 评估核心流媒体业务是否达标 (只要 YT_PR 或 YT_MU 其一达标,即视为成功)
|
||||
YT_MATCH=0
|
||||
|
||||
# Premium 命中目标区域
|
||||
[ "$YT_PR_GL" == "$TARGET_CC" ] && YT_MATCH=1
|
||||
|
||||
# Music 命中目标区域
|
||||
[ "$YT_MU_GL" == "$TARGET_CC" ] && YT_MATCH=1
|
||||
|
||||
# ------------------------------------------------------
|
||||
# YT 主业务达标
|
||||
# ------------------------------------------------------
|
||||
if [ $YT_MATCH -eq 1 ]; then
|
||||
|
||||
# Jump 雷达漂移
|
||||
# 3. 核心业务达标,进一步评估底层路由权重
|
||||
if [ -n "$JUMP_GL" ] && [ "$JUMP_GL" != "$TARGET_CC" ]; then
|
||||
|
||||
# YT 解锁了,但基础跳转 IP 库漂移了 (降级为 ✅,但备注底层漂移)
|
||||
STATUS="✅ 目标区域达成 (YT主导成功, Jump副雷达漂移至 ${JUMP_GL}) | Prem: ${YT_PR_GL:-无} | Music: ${YT_MU_GL:-无}"
|
||||
|
||||
else
|
||||
|
||||
STATUS="✅ 目标区域达成 (Jump: ${JUMP_GL:-无} | Prem: ${YT_PR_GL:-无} | Music: ${YT_MU_GL:-无}"
|
||||
|
||||
# 完美达成
|
||||
STATUS="✅ 目标区域达成 (Jump: ${JUMP_GL:-无} | Prem: ${YT_PR_GL:-无} | Music: ${YT_MU_GL:-无})"
|
||||
fi
|
||||
|
||||
# ------------------------------------------------------
|
||||
# 核心业务未达标
|
||||
# ------------------------------------------------------
|
||||
else
|
||||
|
||||
# YouTube 流媒体核心未能解锁目标区域,宣判漂移
|
||||
STATUS="⚠️ 区域发生漂移!目标 $TARGET_CC,实际 (Jump: ${JUMP_GL:-无} | Prem: ${YT_PR_GL:-无} | Music: ${YT_MU_GL:-无})"
|
||||
|
||||
fi
|
||||
fi
|
||||
|
||||
# ----------------------------------------------------------
|
||||
# 输出最终结果
|
||||
# ----------------------------------------------------------
|
||||
log "$MODULE_NAME" "SCORE" "自检结论: $STATUS"
|
||||
|
||||
# [V4.1.1] 定期清理 Cookie 垃圾防爆栈 (清理超过 14 天的 Cookie)
|
||||
find "$COOKIE_DIR" -type f -name "google_*.txt" -mtime +14 -delete 2>/dev/null || true
|
||||
|
||||
log "$MODULE_NAME" "END " "========== 会话结束,释放进程 =========="
|
||||
Reference in New Issue
Block a user