Repository Wiki
jason5ng32/MyIP

隐身检测与身份画像交叉分析

本页说明 MyIP 如何代理隐身检测结果查询、转发身份画像评估,以及通过浏览器侧 Cloudflare Trace 获取网络出口观测。重点是请求上下文、上游边界、结果语义和异常处理,而非推测未包含在本地实现中的评分算法。

目的与范围

本页覆盖 GET /api/invisibility、POST /api/persona/evaluate、probeTrace() 和两个后端处理器共用的超时请求机制。路由注册可见 backend-server.js。

“交叉分析”需要区分两层含义:

  • 本地可确认的观测与传输:网络出口国家、连接协议等信号的采集,以及将调用者提交的画像和请求上下文发送到评估服务。
  • 上游负责的解释与评分:身份画像处理器明确将评价交给主 IPCheck.ing API,本部署不包含该评价实现。现有证据不能证明隐身检测结果会自动作为画像评估输入,也不能给出权重、风险阈值或完整报告字段。

浏览器指纹、WebRTC、DNS 泄漏、登录界面和部署配置属于相邻主题,本页不展开其内部实现。当前运行上下文未提供这些主题的目录链接,因此不构造未经确认的 Wiki 地址。前端页面编排、完整画像 DTO、评分实现及持久化策略不在已读取源码范围内。

概述

这组能力提供两个不同的接口模型:

能力输入本地职责输出
隐身检测查询查询参数 id校验 ID、附加部署密钥、查询上游、转换部分状态上游 JSON,或 pending/错误对象
身份画像评估含真值 persona.country 的请求体验证基本入口条件、重建请求头、转发完整 JSON保留上游 HTTP 状态的 JSON
网络出口观测无参数从浏览器请求 Cloudflare Trace 并解析可用性、国家、机房、HTTP 和 TLS 信息

身份画像处理器的注释描述了“一份 observation 输入,一份 graded report 输出”的约定,并指出结果由标识符和枚举组成,前端负责四语言文案。这是接口分工说明,不是本地评分模型定义。来源:persona.js。

架构

Loading diagram...

Sources: backend-server.js、invisibility-test.js、persona.js、fetch-with-timeout.js、probe-server.js。

图中刻意不连接 probeTrace() 与画像 POST 接口:已读代码证明探针存在,但未包含将探针结果装入请求体的前端调用链。浏览器探测与后端上游代理也是两条不同的网络路径,不能将后端服务器出口当成浏览器出口。

隐身检测:从 ID 到结果状态

输入验证与请求构造

处理器依次执行以下操作:

  1. 从 req.query.id 取值;缺失或假值返回 HTTP 400,错误为 No ID provided。
  2. 要求 ID 是长度恰为 28 的 ASCII 字母数字字符串;不满足则返回 HTTP 400,错误为 Invalid ID。
  3. 读取 IPCHECKING_API_KEY;缺失返回 HTTP 500,错误为 API key is missing。
  4. 读取 IPCHECKING_API_ENDPOINT,拼接 /getpdresult/{id}?apikey={apikey}。
  5. 调用 fetchUpstream(),将 req.headers 展开转发给上游。

严格限制 ID 的字符集也约束了其作为 URL 路径片段的形式,但代码没有证明它本身承担用户认证或授权功能。该入口只查询结果,不包含启动测试或生成 ID 的实现。来源:invisibility-test.js。

待完成、配额与登录状态

处理器不会把所有非 2xx 响应都当作系统错误。上游 404 的源码注释明确表示“结果尚未计算完成”,用于前端启动测试后的轮询阶段;本地把它转换为默认 HTTP 200 的 { status: 'pending' }。因此,HTTP 成功并不等于测试完成。

上游情况本地响应处理意义
404HTTP 200,status: 'pending'结果未就绪,不记错误日志
429HTTP 429,code: 'quota_exceeded'上游月度配额耗尽;error 优先使用上游值
401 或 403保留状态,返回 error优先采用上游 message,否则 Sign in required
其他非成功状态HTTP 500,error: error.message提取上游错误详情、抛错并记录日志
成功且 JSON 可解析默认 HTTP 200,上游 JSON不重建报告结构
请求或 JSON 解析异常HTTP 500,error: error.message记录 invisibility-test upstream request failed

来源:invisibility-test.js。前端轮询间隔、最大次数以及停止条件未在已读代码中确认。

身份画像:保留上下文的薄代理

校验顺序与边界

画像处理器先检查方法必须为 POST,再检查密钥和上游地址,最后检查 req.body?.persona?.country。方法不匹配返回 405;配置缺失返回 500;缺少真值 country 返回 400。

这里不是完整的数据验证:代码没有校验 country 是否为两字母国家码,也没有在本地限制其类型、枚举或其他 observation 字段。不能把该真值检查解释为完整 DTO 验证。构建的上游地址是 /persona/evaluate,密钥通过 URL.searchParams.set('key', apiKey) 加入。

来源:persona.js。

为什么需要重建请求头

评估服务需要调用者上下文,因此请求头原则上保留;但 callerHeaders() 先复制请求头,再删除 host、content-length、content-type、connection、transfer-encoding。处理器随后显式写入 Content-Type: application/json 并重新序列化请求体。

这使新请求的目标地址和实体编码不依赖上一跳的长度、主机及连接信息。它是代码中列出的五项过滤,而非可直接假定为完整的通用代理头清理器。隐身检测代理没有使用该过滤函数,二者行为不应混淆。来源:persona.js。

状态透传而非统一包装

请求成功到达上游后,不检查 apiResponse.ok,而是解析 JSON 并保留 apiResponse.status。JSON 无法解析时使用空对象 {},仍保留原 HTTP 状态。因此,上游拒绝和上游不可达是两类情况:前者保留状态与可解析载荷,后者被记录为 persona evaluate upstream fetch failed 并返回 HTTP 502、Upstream fetch failed。

Loading diagram...

Sources: backend-server.js、persona.js、fetch-with-timeout.js。

浏览器网络出口观测

probeTrace() 请求固定地址 https://cloudflare.com/cdn-cgi/trace。源码将其 loc 描述为出口国家的独立第二意见;它提供外部观察视角,而非证明一个人的真实所在地或身份。

parseTraceBody(text) 将输入转换为字符串、按换行分割,只处理第一个 = 位于非零位置的行。键和值分别去除两端空白,值内后续的 = 会保留;同名键由后面的行覆盖。HTTP 成功后,探针返回以下字段:

字段来源/语义缺失时
availableHTTP 成功且解析过程未抛错成功路径为 true
countryloc 转大写空字符串
coloCloudflare 机房标识空字符串
httpProtocolhttp空字符串
tlsVersiontls空字符串

非成功 HTTP 状态返回 { available: false, reason: 'http-状态码' };AbortError 返回 timeout,其他异常返回 unreachable。特别地,HTTP 200 但缺少 loc 仍得到 available: true,调用方必须区分“请求可用”和“国家字段有效”。源码:probe-server.js。

使用示例:实际实现片段

以下示例直接摘自仓库,展示接口处理方式,不是虚构的客户端调用或报告格式。

1. 隐身检测 ID 校验

javascript
1function isValidUserID(userID) { 2 if (typeof userID !== 'string') return false; 3 if (userID.length !== 28 || !/^[a-zA-Z0-9]+$/.test(userID)) return false; 4 return true; 5}

Source: invisibility-test.js。

该检查会拒绝数组、数字、空格、标点和非 ASCII 字母,不会将输入自动转换成字符串。

2. 将尚未完成转换成业务状态

javascript
if (apiResponse.status === 404) { return res.json({ status: 'pending' }); }

Source: invisibility-test.js。

这是隐身检测与通用 HTTP 代理的关键差异:404 在此不是“查询接口不存在”,而是上游约定的未完成结果。

3. 转发画像 observation

javascript
1 const apiResponse = await fetchUpstream(url, { 2 method: 'POST', 3 headers: { ...callerHeaders(req), 'Content-Type': 'application/json' }, 4 body: JSON.stringify(req.body), 5 });

Source: persona.js。

代码转发整个请求体,不只转发 persona.country。因此后续增加 observation 字段时,仍需要核对上游契约,不能以本地能序列化为兼容性保证。

4. 带超时且不使用浏览器缓存的探测

javascript
1const withTimeout = async (url, options = {}) => { 2 const controller = new AbortController(); 3 const timer = setTimeout(() => controller.abort(), TIMEOUT_MS); 4 try { 5 return await fetch(url, { cache: 'no-store', signal: controller.signal, ...options }); 6 } finally { 7 clearTimeout(timer); 8 } 9};

Source: probe-server.js。

当前 probeTrace() 不传 options,因此使用自身的取消信号和 no-store。若未来给该内部函数传入 signal 或 cache,后置展开的 options 会覆盖默认值;它不同于共享请求封装的取消信号合并机制。

配置与超时

配置/参数类型默认值作用及限制
IPCHECKING_API_KEY环境变量字符串无本地默认值两个代理必需;隐身查询使用 apikey 查询参数,画像使用 key
IPCHECKING_API_ENDPOINT环境变量字符串无本地默认值上游 API 基址;画像显式检查存在性,隐身查询不做该检查
fetchUpstream 的 timeoutMs数值,毫秒8000两个处理器没有覆盖它
fetchWithTimeout 的 timeoutMs数值,毫秒5000通用封装默认值,后端预设会覆盖为 8000
upstreamUserAgent运行时值null通过 setUpstreamUserAgent(ua) 设置,仅在调用者未携带 UA 时注入
TRACE_URL常量字符串https://cloudflare.com/cdn-cgi/trace浏览器出口观测地址,不是已确认的环境配置项
TIMEOUT_MS常量数值,毫秒6000Trace 请求超时

来源:invisibility-test.js、persona.js、fetch-with-timeout.js、probe-server.js。

共享封装为每次调用创建独立 AbortController,同时监听调用者已有的 signal:已取消则立即取消新控制器,否则通过一次性监听器传播取消。定时器在 fetch 完成或失败后清除。需要注意,封装返回的是 Response,随后在处理器中执行的 response.json() 不处于这个定时器的保护范围内,因此不宜将 8 秒称为包含完整响应体读取的端到端总时限。

UA 注入会大小写不敏感地检查普通对象中的键,也支持 Headers.has();数组形式的 headers 被视为不注入。由于两种代理都会携带调用者请求头,已有浏览器 UA 不会被部署标识覆盖。来源:fetch-with-timeout.js。

API 参考

这些文件为 JavaScript,未声明 TypeScript 类型。下表中的返回说明来自实现行为,不是额外定义的类型契约。

接口/函数参数返回与失败行为
GET /api/invisibility查询参数 id,必需,28 位字母数字字符串上游 JSON、pending 或错误 JSON;状态转换见前文
POST /api/persona/evaluateJSON 请求体,至少 persona.country 为真值上游状态与 JSON;本地 400/405/500,转发异常 502
probeTrace()无Promise,兑现为可用信息或带 reason 的不可用对象;内部捕获探测异常
parseTraceBody(text)可经 String(text) 转换的值键值对象;不校验国家码或字段完整性
fetchWithTimeout(url, init = {})fetch 地址与选项,另支持 timeoutMsPromise,成功返回 Response;异常继续向调用方传播
fetchUpstream(url, init = {})同上应用 8 秒预设及可选 UA 后返回底层 Promise
setUpstreamUserAgent(ua)UA 值,假值重置为 null无显式返回值;更新模块级配置

来源:invisibility-test.js、persona.js、probe-server.js、fetch-with-timeout.js。

故障、边界与并发

容易误判的边界

  • URL 构造在 try 之外:两个处理器都在进入请求异常捕获前执行 new URL(...)。非法基址导致的 URL 构造异常不经过各自的 500/502 捕获分支;最终由哪一层处理,不能从这两个文件确定。
  • 配置错误文案并不精确区分原因:画像缺密钥或缺基址都返回 API key is missing;排障时应同时检查两项。隐身查询只检查密钥存在性。
  • JSON 失败策略不同:画像响应无法解析时使用 {};隐身查询的正常响应无法解析时进入 500 分支。画像的空对象不代表成功生成了空报告。
  • 没有本地评分保证:画像中的 country 真值检查不能保证输入国家合法,也不能证明观测数据可信。
  • 探测失败不是风险结论:Trace 的 timeout、unreachable 或 HTTP 错误只能证明此次观测没有获得可用结果,不能直接推导为匿名成功、代理存在或身份欺骗。

这些差异来自 persona.js、invisibility-test.js 和 probe-server.js。

并发与数据生命周期

两个处理器均在请求内构造 URL 和响应,不在已读实现中写入数据库、缓存报告或维护任务队列。画像文件明确将评估描述为逐访问者且不缓存;Trace 请求显式使用 cache: 'no-store'。这些局部行为不能证明外部评估服务没有保存数据,也不能替代反向代理或部署层的缓存审计。

每次 fetch 的控制器、定时器和画像请求头副本都是独立的;没有观察到跨请求锁、合并请求、去重或重试。upstreamUserAgent 是共享模块变量,属于例外的全局运行时配置。身份画像请求体及保留的调用者请求头会离开当前部署发送到上游,隐身查询也会转发调用者请求头;这里的“隐身检测”不应被理解为不向任何第三方传输信息。

运维、性能与扩展

排障顺序

  1. 先分清业务状态与故障:隐身 200 pending 是未完成;429 是上游配额;401/403 是登录相关状态。不要仅按非 2xx 数量评估系统故障。
  2. 确认配置与 URL:检查密钥、基址和 URL 合法性;画像密钥参数名与隐身查询不同。
  3. 查看指定日志:隐身查询异常记录 invisibility-test upstream request failed,画像请求异常记录 persona evaluate upstream fetch failed。预期的隐身 pending、配额及登录分支不会调用错误日志。
  4. 核对耗时边界:后端请求预设为 8 秒,Trace 为 6 秒;响应体读取与前端轮询总时长不能由这两个数字推导。
  5. 检查响应语义:画像保留上游状态,即使载荷回退为 {};Trace 的可用标志与国家字段完整性应分别检查。

本地代码没有自动重试或退避策略。重复请求会重复访问上游;是否由页面禁用重复点击、限制并发或停止轮询,未在本次源码中确认。

安全扩展边界

  • 若扩展画像信号,应同步确认上游 observation 协议、枚举以及前端解释方式;薄代理不会替代这些契约验证。
  • 若增加国家或字段校验,应将其视为接口行为变化;当前实现仅检查真值。
  • 若统一两个代理的请求头清理,应考虑评估对调用者上下文的依赖,不能不加区分地删除所有头。
  • 若增加缓存,应先识别访问者隔离要求;画像是逐访问者评估,不能因相同国家参数而共享报告。
  • 若增加重试,应避免对画像拒绝、隐身配额耗尽或需要登录的响应进行无条件重试。

以上是依据现有边界提出的维护建议,不是仓库已经实现的机制。

测试证据与验证范围

源码检索发现 persona-server-probe.test.js 导入 probeTrace、parseTraceBody 与地理位置探针,但本页没有读取其断言,不能据此声明具体覆盖范围。画像处理器的注释提到方法防御分支有测试,实际测试断言同样未在本次读取范围内;本次任务也未运行测试。

建议回归时优先检查:ID 类型与长度、404 到 pending 的转换、429/401/403 分支、画像空或非法 JSON 响应、缺失基址、Trace 缺少 loc、超时与并发调用隔离。这些是根据已验证分支列出的验证建议,不代表已有自动化测试清单。

相关链接

Sources

(4 files)