From 91600c4abe4c2f87ff943a5a134727b0163d272d Mon Sep 17 00:00:00 2001 From: win Date: Wed, 25 Mar 2026 13:00:52 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=20Mac=20=E5=92=8C=20?= =?UTF-8?q?Linux=20=E5=85=A8=E9=87=8F=E6=8C=87=E7=BA=B9=E9=AA=8C=E8=AF=81?= =?UTF-8?q?=E8=84=9A=E6=9C=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- antigravity/maintenance/test-linux.sh | 184 ++++++++++++++++++++++++++ antigravity/maintenance/test-mac.sh | 117 ++++++++++++++++ 2 files changed, 301 insertions(+) create mode 100755 antigravity/maintenance/test-linux.sh create mode 100755 antigravity/maintenance/test-mac.sh diff --git a/antigravity/maintenance/test-linux.sh b/antigravity/maintenance/test-linux.sh new file mode 100755 index 00000000..bb4beff5 --- /dev/null +++ b/antigravity/maintenance/test-linux.sh @@ -0,0 +1,184 @@ +#!/bin/bash +# test-linux.sh — Linux 服务器全量指纹验证脚本 +# 用途:验证所有 TCP/OS 层伪装 + Node.js proxy 状态 +# 运行方式:sudo bash test-linux.sh +# +# 注意:sysctl 和 iptables 检查需要 sudo + +set -euo pipefail +GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' +ok() { echo -e "${GREEN}✅ $*${NC}"; } +fail() { echo -e "${RED}❌ $*${NC}"; } +info() { echo -e "${YELLOW}ℹ $*${NC}"; } + +PROXY_PORT="${PROXY_PORT:-3456}" + +echo "══════════════════════════════════════════════" +echo " Linux 服务器指纹伪装验证" +echo "══════════════════════════════════════════════" + +# ── 1. 时区 ──────────────────────────────────────────────── +echo "" +echo "【1】系统时区" +TZ_NOW=$(timedatectl show -p Timezone --value 2>/dev/null || cat /etc/timezone 2>/dev/null || date +%Z) +echo " 当前时区: $TZ_NOW" +echo " 当前时间: $(date)" +if [[ "$TZ_NOW" == "America/New_York" ]]; then + ok "时区正确(America/New_York)" +else + fail "时区错误(应为 America/New_York,当前: $TZ_NOW)" + info "修复: sudo timedatectl set-timezone America/New_York" +fi + +# ── 2. TCP 时间戳 ────────────────────────────────────────── +echo "" +echo "【2】TCP 时间戳(防 uptime 推算)" +TS=$(sysctl -n net.ipv4.tcp_timestamps 2>/dev/null || echo "unknown") +echo " net.ipv4.tcp_timestamps = $TS" +if [[ "$TS" == "0" ]]; then + ok "TCP 时间戳已禁用" +else + fail "TCP 时间戳未禁用(当前: $TS,应为 0)" + info "修复: sudo sysctl -w net.ipv4.tcp_timestamps=0" +fi + +# ── 3. TTL ───────────────────────────────────────────────── +echo "" +echo "【3】出站 TTL(macOS 特征)" +TTL=$(sysctl -n net.ipv4.ip_default_ttl 2>/dev/null || echo "unknown") +echo " net.ipv4.ip_default_ttl = $TTL" +if [[ "$TTL" == "64" ]]; then + ok "TTL=64(macOS/Linux 标准值)" +else + fail "TTL 不为 64(当前: $TTL)" +fi + +# ── 4. TCP Window Size ───────────────────────────────────── +echo "" +echo "【4】TCP Window Size(macOS 特征)" +RMEM=$(sysctl -n net.ipv4.tcp_rmem 2>/dev/null || echo "unknown") +echo " net.ipv4.tcp_rmem = $RMEM" +if [[ "$RMEM" == *"65535"* ]]; then + ok "Window Size 包含 65535(macOS 特征)" +else + fail "Window Size 未伪装(应含 65535,当前: $RMEM)" + info "修复: sudo sysctl -w net.ipv4.tcp_rmem='4096 65535 6291456'" +fi + +# ── 5. iptables 规则 ─────────────────────────────────────── +echo "" +echo "【5】iptables 指纹防护链" +if iptables -L MG_FINGERPRINT -n 2>/dev/null | grep -q "MG:"; then + ok "MG_FINGERPRINT 链存在" + RULES=$(iptables -L MG_FINGERPRINT -n 2>/dev/null | grep -c "MG:" || echo 0) + echo " 规则数: $RULES 条" +else + fail "MG_FINGERPRINT 链不存在,运行 setup-firewall.sh apply" +fi + +if iptables -t mangle -L MG_FINGERPRINT_TTL -n 2>/dev/null | grep -q "TTL"; then + ok "TTL mangle 链存在" +else + fail "TTL mangle 链不存在" +fi + +# ── 6. QUIC 阻断验证 ─────────────────────────────────────── +echo "" +echo "【6】QUIC/UDP 阻断" +if iptables -L MG_FINGERPRINT -n 2>/dev/null | grep -q "udp.*443.*DROP"; then + ok "UDP 443 QUIC 已阻断" +else + fail "UDP 443 未阻断" +fi + +# ── 7. Node.js 版本 ──────────────────────────────────────── +echo "" +echo "【7】Node.js 版本" +if command -v node &>/dev/null; then + NODE_VER=$(node --version) + echo " Node.js: $NODE_VER" + if [[ "$NODE_VER" == v22* ]]; then + ok "Node.js v22.x — 与 Claude CLI 版本匹配" + else + fail "Node.js 不是 v22.x(当前: $NODE_VER),JA4 指纹可能不匹配" + fi +else + info "Node.js 未在宿主机安装(Docker 部署无需宿主机 Node)" +fi + +# ── 8. node-tls-proxy 健康 ───────────────────────────────── +echo "" +echo "【8】node-tls-proxy 健康(端口 $PROXY_PORT)" +if curl -sf "http://127.0.0.1:${PROXY_PORT}/__health" -o /tmp/health.json 2>/dev/null; then + NODE_IN_PROXY=$(python3 -c "import json; d=json.load(open('/tmp/health.json')); print(d.get('node','?'))" 2>/dev/null) + SESSIONS=$(python3 -c "import json; d=json.load(open('/tmp/health.json')); print(d.get('sessions',0))" 2>/dev/null) + H2HOSTS=$(python3 -c "import json; d=json.load(open('/tmp/health.json')); print(','.join(d.get('h2Hosts',[])))" 2>/dev/null) + TELEMETRY=$(python3 -c "import json; d=json.load(open('/tmp/health.json')); print(d.get('telemetry','?'))" 2>/dev/null) + ok "Proxy 运行正常" + echo " Node版本: $NODE_IN_PROXY" + echo " Sessions: $SESSIONS" + echo " H2已建立: ${H2HOSTS:-(无,首次请求后会建立)}" + echo " 遥测: $TELEMETRY" + if [[ "$NODE_IN_PROXY" == v22* ]]; then + ok "Proxy 内置 Node.js v22.x ✅" + else + fail "Proxy 内置 Node 版本: $NODE_IN_PROXY(应为 v22.x)" + fi +else + fail "Proxy 未响应(端口 $PROXY_PORT)" + info "检查: docker ps | grep node-tls-proxy" +fi + +# ── 9. Node.js JA4 指纹(在 proxy 容器内测) ────────────── +echo "" +echo "【9】Node.js JA4 TLS 指纹" +if docker ps --format '{{.Names}}' 2>/dev/null | grep -q "node-tls-proxy"; then + JA4=$(docker exec node-tls-proxy node -e " +const https = require('https'); +https.get('https://tls.peet.ws/api/all', res => { + let d=''; res.on('data',c=>d+=c); + res.on('end',()=>{ try{console.log(JSON.parse(d).tls.ja4);}catch(e){console.log('err');} }); +}).on('error',e=>console.log('err:'+e.message)); +" 2>/dev/null || echo "exec_failed") + echo " Proxy JA4: $JA4" + if [[ "$JA4" == t13* ]]; then + ok "JA4 指纹正常(TLS 1.3)" + else + fail "JA4 获取失败: $JA4" + fi +elif command -v node &>/dev/null; then + JA4=$(node -e " +const https = require('https'); +https.get('https://tls.peet.ws/api/all', res => { + let d=''; res.on('data',c=>d+=c); + res.on('end',()=>{ try{console.log(JSON.parse(d).tls.ja4);}catch(e){console.log('err');} }); +}).on('error',e=>console.log('err:'+e.message)); +" 2>/dev/null || echo "err") + echo " 宿主机 JA4: $JA4" + [[ "$JA4" == t13* ]] && ok "JA4 正常" || fail "JA4 失败" +else + info "跳过 JA4 测(无 docker exec 也无宿主机 node)" +fi + +# ── 10. 出口 IP 验证 ─────────────────────────────────────── +echo "" +echo "【10】出口 IP 信息" +IP_INFO=$(curl -sf --max-time 5 "https://ipinfo.io/json" 2>/dev/null || echo '{}') +IP=$(echo "$IP_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('ip','?'))" 2>/dev/null) +ORG=$(echo "$IP_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('org','?'))" 2>/dev/null) +CITY=$(echo "$IP_INFO" | python3 -c "import json,sys; d=json.load(sys.stdin); print(d.get('city','?')+', '+d.get('region','?'))" 2>/dev/null) +echo " IP: $IP" +echo " ISP: $ORG" +echo " 城市: $CITY" +if echo "$ORG" | grep -qiE "residential|comcast|verizon|optimum|spectrum|altice|fios|att|xfinity"; then + ok "ISP 看起来是住宅宽带 ✅" +elif echo "$ORG" | grep -qiE "datacenter|hosting|cloud|amazon|google|microsoft|linode|vultr|digital"; then + fail "ISP 是数据中心 IP,建议换住宅宽带" +else + info "ISP 未能自动判断,请人工核查: $ORG" +fi + +echo "" +echo "══════════════════════════════════════════════" +echo " 验证完成" +echo "══════════════════════════════════════════════" diff --git a/antigravity/maintenance/test-mac.sh b/antigravity/maintenance/test-mac.sh new file mode 100755 index 00000000..9d015336 --- /dev/null +++ b/antigravity/maintenance/test-mac.sh @@ -0,0 +1,117 @@ +#!/bin/bash +# test-mac.sh — 本机(Mac)指纹验证脚本 +# 用途:验证 Node.js TLS 指纹、H2 连通性 +# 运行方式:bash test-mac.sh + +set -euo pipefail +GREEN='\033[0;32m' RED='\033[0;31m' YELLOW='\033[1;33m' NC='\033[0m' +ok() { echo -e "${GREEN}✅ $*${NC}"; } +fail() { echo -e "${RED}❌ $*${NC}"; } +info() { echo -e "${YELLOW}ℹ $*${NC}"; } + +echo "══════════════════════════════════════" +echo " MAC 本地指纹验证" +echo "══════════════════════════════════════" + +# ── 1. Node.js 版本 ──────────────────────────────────────── +echo "" +echo "【1】Node.js 版本" +NODE_VER=$(node --version 2>/dev/null || echo "未安装") +echo " 本机 Node: $NODE_VER" +if [[ "$NODE_VER" == v22* ]]; then + ok "Node.js v22.x — 与 Claude CLI 内置版本匹配" +else + fail "Node.js 版本不是 v22.x(当前: $NODE_VER),JA4 指纹可能不一致" + info "安装 v22: nvm install 22 && nvm use 22" +fi + +# ── 2. Node.js JA4 TLS 指纹 ──────────────────────────────── +echo "" +echo "【2】Node.js TLS JA4 指纹(服务器实际产生的指纹)" +JA4=$(node -e " +const https = require('https'); +https.get('https://tls.peet.ws/api/all', res => { + let d=''; res.on('data',c=>d+=c); + res.on('end',()=>{ + try { console.log(JSON.parse(d).tls.ja4); } catch(e){ console.log('parse_error'); } + }); +}).on('error', e => console.log('error:'+e.message)); +" 2>/dev/null) +echo " JA4: $JA4" +if [[ "$JA4" == t13* ]]; then + ok "TLS 1.3,看起来是合法的 Node.js 指纹" +else + fail "JA4 获取失败或格式异常: $JA4" +fi + +# ── 3. H2 连接 api.anthropic.com ─────────────────────────── +echo "" +echo "【3】HTTP/2 连通性(Anthropic)" +H2_RESULT=$(node -e " +const http2 = require('http2'); +const s = http2.connect('https://api.anthropic.com', {}, () => { + console.log('ok:' + s.socket.alpnProtocol); + s.close(); +}); +s.on('error', e => { console.log('err:'+e.message); process.exit(0); }); +setTimeout(()=>{ console.log('timeout'); process.exit(0); }, 5000); +" 2>/dev/null) +if [[ "$H2_RESULT" == ok:h2 ]]; then + ok "Anthropic H2 连接成功(alpnProtocol: h2)" +else + fail "H2 连接失败: $H2_RESULT" +fi + +# ── 4. H2 连接 googleapis.com ────────────────────────────── +echo "" +echo "【4】HTTP/2 连通性(Google / Gemini)" +H2G=$(node -e " +const http2 = require('http2'); +const s = http2.connect('https://generativelanguage.googleapis.com', {}, () => { + console.log('ok:' + s.socket.alpnProtocol); + s.close(); +}); +s.on('error', e => { console.log('err:'+e.message); process.exit(0); }); +setTimeout(()=>{ console.log('timeout'); process.exit(0); }, 5000); +" 2>/dev/null) +if [[ "$H2G" == ok:h2 ]]; then + ok "Google API H2 连接成功" +else + fail "Google API H2 连接失败: $H2G" +fi + +# ── 5. 本地 proxy 健康检查(如果本地起了) ───────────────── +echo "" +echo "【5】本地 node-tls-proxy 健康(端口 3456)" +PROXY_PORT="${PROXY_PORT:-3456}" +if curl -sf "http://127.0.0.1:${PROXY_PORT}/__health" -o /tmp/proxy_health.json 2>/dev/null; then + SESSIONS=$(python3 -c "import json,sys; d=json.load(open('/tmp/proxy_health.json')); print(d.get('sessions',0))" 2>/dev/null || echo "?") + H2HOSTS=$(python3 -c "import json,sys; d=json.load(open('/tmp/proxy_health.json')); print(','.join(d.get('h2Hosts',[])))" 2>/dev/null || echo "?") + ok "Proxy 运行中 | sessions=$SESSIONS | h2Hosts=$H2HOSTS" +else + info "本地未运行 node-tls-proxy(端口 $PROXY_PORT),跳过" +fi + +# ── 6. Jitter 延迟分布(如果 proxy 运行中)──────────────── +echo "" +echo "【6】Jitter 延迟测试(5次请求,通过本地 proxy)" +if curl -sf "http://127.0.0.1:${PROXY_PORT:-3456}/__health" -o /dev/null 2>/dev/null; then + for i in {1..5}; do + START=$(date +%s%3N) + curl -sf -X POST "http://127.0.0.1:${PROXY_PORT:-3456}/v1/messages" \ + -H "x-forwarded-host: api.anthropic.com" \ + -H "content-type: application/json" \ + -d '{"model":"claude-opus-4-5","max_tokens":1}' -o /dev/null 2>/dev/null || true + ELAPSED=$(($(date +%s%3N) - START)) + echo " 请求 $i: ${ELAPSED}ms" + done + ok "延迟应在 80-1200ms 之间,非均匀分布" +else + info "本地未运行 proxy,跳过 Jitter 测试" +fi + +echo "" +echo "══════════════════════════════════════" +echo " Mac 验证完成" +echo " 关键指纹: $JA4" +echo "══════════════════════════════════════"