www.apple.com 为伪装地址,前端警告消失
This commit is contained in:
+73
-10
@@ -234,6 +234,39 @@ generate_keys() {
|
||||
fi
|
||||
}
|
||||
|
||||
# ===== 候选伪装站的技术校验 =====
|
||||
# 只看 xray tls ping 的「Pinging with SNI」那一段:REALITY 实际用的是带 SNI 的
|
||||
# 握手结果,无 SNI 段返回的往往是另一张证书(如 Google 的 invalid2.invalid,
|
||||
# 才 895 字节),照它判会误判。
|
||||
REALITY_DEST_CERT_LEN=""
|
||||
check_reality_dest() {
|
||||
local site="$1" out len
|
||||
REALITY_DEST_CERT_LEN=""
|
||||
|
||||
local raw
|
||||
raw=$(/usr/local/bin/xray tls ping "$site" 2>&1)
|
||||
# 区分「当前 xray 没有 tls ping 子命令」和「这个域名校验不通过」:
|
||||
# 前者不该阻断部署,后者必须判失败。有 "TLS ping" 头即说明子命令存在。
|
||||
if ! echo "$raw" | grep -q "TLS ping"; then
|
||||
warn " ${site}: 当前 xray 不支持 tls ping,跳过技术校验"
|
||||
return 0
|
||||
fi
|
||||
|
||||
out=$(echo "$raw" | sed -n '/Pinging with SNI/,$p')
|
||||
echo "$out" | grep -q "Handshake succeeded" || return 1
|
||||
echo "$out" | grep -q "TLS Version:.*TLS 1\.3" || return 1
|
||||
|
||||
len=$(echo "$out" | grep -oE "Certificate chain's total length:[[:space:]]*[0-9]+" \
|
||||
| grep -oE '[0-9]+$' | head -1)
|
||||
[ -n "$len" ] || return 1
|
||||
# xtls/reality 对 target 握手报文有 8192 字节硬编码上限,超出直接握手失败
|
||||
# (XTLS/Xray-core#6356:www.microsoft.com 的证书记录 8273 字节即触发)
|
||||
[ "$len" -lt 8192 ] || return 1
|
||||
|
||||
REALITY_DEST_CERT_LEN="$len"
|
||||
return 0
|
||||
}
|
||||
|
||||
# ===== 3. 选择 Reality 伪装目标 =====
|
||||
select_reality_dest() {
|
||||
if [ "$MODE" != "reality" ]; then
|
||||
@@ -242,7 +275,27 @@ select_reality_dest() {
|
||||
|
||||
step "4/8 选择 Reality 伪装目标"
|
||||
|
||||
local candidates=("www.microsoft.com" "dl.google.com" "www.apple.com" "www.amazon.com")
|
||||
# 候选伪装站必须同时满足两类条件。
|
||||
#
|
||||
# 【技术条件】TLS 1.3 + 证书链总长 < 8192 字节。由 check_reality_dest 运行时实测。
|
||||
#
|
||||
# 【客户端路由条件】SNI 必须会被客户端判成「直连」——这条不直观,但踩过坑。
|
||||
# TUN 模式下,客户端有时会把「连接本代理服务器」这件事本身也抓进代理
|
||||
# (v2rayN 的 sing-box+xray 双核心架构靠进程嗅探防回环,Windows 上有竞态,
|
||||
# 实测约 2843:1584 的失败率)。这种回环连接的去向完全由 SNI 决定:
|
||||
#
|
||||
# SNI 被判直连 → 连接真的到达本服务器 → REALITY 握手成功 → 用户无感
|
||||
# SNI 被判走代理 → 进隧道 → 服务器替客户端连了真正的伪装站
|
||||
# → 客户端收到真证书 → 刷屏 REALITY: received real certificate
|
||||
#
|
||||
# 实测(v2rayN 默认规则模板,geosite:google → proxy 排在 geosite:cn → direct 之前):
|
||||
# www.apple.com / *.apple.com 命中 geosite:cn 安全
|
||||
# dl.google.com 命中 geosite:google 不安全(本仓库踩过)
|
||||
# www.microsoft.com 两者都不命中 → final:proxy 不安全
|
||||
# www.amazon.com 两者都不命中 → final:proxy 不安全
|
||||
#
|
||||
# 故候选只保留 Apple 系域名。更换前请先确认新域名命中客户端的直连规则。
|
||||
local candidates=("www.apple.com" "swdist.apple.com" "updates.cdn-apple.com" "itunes.apple.com")
|
||||
REALITY_DEST="${REALITY_DEST:-}"
|
||||
REALITY_SNI="${REALITY_SNI:-}"
|
||||
|
||||
@@ -259,6 +312,10 @@ select_reality_dest() {
|
||||
warn "注意:更换会改变 SNI,届时所有客户端链接都必须同步更新"
|
||||
else
|
||||
log "伪装目标连通性正常 (${ms}ms)"
|
||||
if ! check_reality_dest "$REALITY_DEST"; then
|
||||
warn "伪装目标 ${REALITY_DEST} 未通过 REALITY 技术校验"
|
||||
warn "(要求 TLS 1.3 且证书链 < 8192 字节),客户端可能握手失败"
|
||||
fi
|
||||
fi
|
||||
return
|
||||
fi
|
||||
@@ -267,29 +324,35 @@ select_reality_dest() {
|
||||
warn "--redetect:将重新挑选伪装目标,原目标为 ${REALITY_DEST}"
|
||||
fi
|
||||
|
||||
local best_dest=""
|
||||
local best_ms=9999
|
||||
|
||||
# 按列表顺序优先,只有前面的不可用才往后顺延——不按延迟排序。
|
||||
# 候选现在都是 Apple 系主机,彼此延迟差在噪声级(实测 1~2ms),
|
||||
# 按延迟挑会让每台机器随机选出不同 SNI,徒增客户端管理成本;
|
||||
# 而 SNI 在所有机器上保持一致,运维和排查都省事得多。
|
||||
local best_dest="" best_ms=""
|
||||
for site in "${candidates[@]}"; do
|
||||
local ms
|
||||
# curl 失败时 %{time_connect} 会输出 0.000000,必须要求 ms > 0,
|
||||
# 否则连不通的站点会被当成「延迟最低」选中
|
||||
# 否则连不通的站点会被当成可用
|
||||
ms=$(curl -so /dev/null -w '%{time_connect}' --max-time 3 "https://${site}" 2>/dev/null \
|
||||
| awk '{printf "%d", $1*1000}') || true
|
||||
if [ -z "$ms" ] || ! [[ "$ms" =~ ^[0-9]+$ ]] || [ "$ms" -le 0 ]; then
|
||||
warn " ${site} 不可达,跳过"
|
||||
continue
|
||||
fi
|
||||
log " ${site} → ${ms}ms"
|
||||
if [ "$ms" -lt "$best_ms" ]; then
|
||||
best_ms=$ms
|
||||
best_dest=$site
|
||||
if ! check_reality_dest "$site"; then
|
||||
warn " ${site} (${ms}ms) 未通过技术校验,跳过"
|
||||
continue
|
||||
fi
|
||||
log " ${site} → ${ms}ms,证书链 ${REALITY_DEST_CERT_LEN:-?} 字节 ✔"
|
||||
best_dest="$site"
|
||||
best_ms="$ms"
|
||||
break
|
||||
done
|
||||
|
||||
if [ -z "$best_dest" ]; then
|
||||
error "所有候选伪装目标都无法连接,请检查服务器网络 / DNS"
|
||||
error "没有候选伪装目标能同时满足「可达」与「REALITY 技术要求」"
|
||||
error "候选列表: ${candidates[*]}"
|
||||
error "可在 .env 中手动指定 REALITY_DEST / REALITY_SNI 后重试"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
Reference in New Issue
Block a user