118 lines
4.9 KiB
Bash
Executable File
118 lines
4.9 KiB
Bash
Executable File
#!/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 "══════════════════════════════════════"
|