qruiqai/leakish
GitHub: qruiqai/leakish
一款浏览器端隐私泄露检测器,通过八大模块检测 WebRTC、指纹、DNS 等泄露风险并提供评分与历史分析。
Stars: 3 | Forks: 1
Leakish
浏览器隐私泄露检测器 —— 包含八大检测模块、风险评分以及
按账户划分的历史记录,全部在你的浏览器中运行。
## 这是什么
打开一个 URL,点击 **Run all**,几秒钟内 Leakish 就会告诉你
你的浏览器正在泄露关于你和你网络的哪些信息 —— 包括 WebRTC、
指纹 API、DNS 以及服务端探测。八个独立模块各自生成类型化的结果
+ 风险信号、一个综合评分(0–100)以及对应的风险等级
(`safe` / `warning` / `critical`)。
已登录的用户可以将扫描结果保存到 MySQL,浏览历史记录,并打开分析
仪表板,其中展示了分布图、指纹哈希重复情况、IP / ASN
时间轴、异常扫描以及两两对比。其他所有功能(检测器本身)无需
账号即可使用 —— 任何人都可以进入 `/app` 并运行扫描。
## 检测模块
| ID | 模块 | 检测内容 |
| --------------------- | -------------------- | ------------------------------------------------------------------------------------------- |
| `network-probe` | 网络出站探测 | 服务端观测到的公网 IP、ASN、国家/地区/城市、VPN/代理/Tor/托管标记、TLS/HTTP |
| `webrtc` | WebRTC | 通过 STUN 获取的公网 IPv4 + IPv6、RFC1918 泄露、mDNS 混淆的 `.local` 候选地址 |
| `browser-fingerprint` | 浏览器指纹 | UA、屏幕、时区、插件、CPU 核心数、设备内存、语言列表、DNT、cookie |
| `canvas-fingerprint` | Canvas / WebGL | 2D + WebGL 渲染器/厂商字符串、文本渲染特性、支持的图像格式 |
| `audio-fingerprint` | Audio | `AudioContext` 采样率、声道、延迟、振荡器输出哈希 |
| `font-detection` | 字体 | 通过 Canvas 宽度差检测对 40 多种命名字体进行探测 |
| `dns` | DNS | DoH 可达性、DNSSEC 信号、解析器地理位置、DNS 泄露启发式检测 |
| `cdp-detection` | 自动化 / 无头模式 | `navigator.webdriver`、CDP 计时、Chromium 独有 API 接口、端口探测 —— 置信度为 0–1 |
每个模块都通过统一的类型化 `DetectionModule
` 接口注册,并独立
运行 —— 某个模块抛出异常不会影响其他模块。每个模块的启用状态会通过带版本号的
key 持久化存储在 `localStorage` 中,在页面刷新后依然保留,并且 **Run all**
按钮只会遍历已启用的模块集合。
## 功能
- **浏览器内检测** —— 每个模块都在用户的浏览器标签页中运行。只有在以下情况服务器才会
参与:(a) 用户已登录并保存扫描结果,(b)
network-probe 模块请求 `/api/detect/network` 以读取其自身服务端观测到的
IP,或 (c) DNS 模块与 `https://dns.google/resolve` 通信。
- **双语界面** —— 完整的中英文对等支持。语言环境存储在
`leakish.locale` cookie 中,它控制着 ``、页面元数据、每一个界面、
每一个 API 错误响应以及 magic-link 登录邮件。
- **身份验证** —— 使用 NextAuth 结合 Google OAuth + magic-link 邮件;
在 MySQL 上使用 Prisma adapter。在开发环境中 Email 是可选的 ——
如果未配置 Mailgun,链接将直接打印到服务器
日志中。
- **编程访问** —— 用户可以在
_Integrations_ 页面生成 `det_…` API key(以 SHA-256 存储,明文仅显示一次)。每个
`/api/detect/*` endpoint 都接受 session cookie 或 Bearer key,因此
可以从 CLI / CI 任务中保存相同的扫描。
- **分析仪表板** 位于 `/scans/analytics` —— 涵盖
时区 / 平台 / 语言 / 屏幕 / WebGL / ASN / 国家 / 字体数量的分布图表,
按类型划分风险等级的指纹哈希重复情况,IP / ASN 时间轴,
多轴异常检测器,以及具有 0–100 相似度评分的两两对比。
- **具有单信号可溯源性的风险模型** —— `lib/risk/assess.ts` 会生成
具有稳定 ID(例如 `webrtc.public-ip-leak`)的类型化 `RiskSignal`、各模块的
摘要,以及一个综合评分。通过 `Messages` 注入实现本地化。
- **幂等保存 + 按用户修剪** —— `POST /api/detect/scans` 接受
`Idempotency-Key` header,将每个用户的上限设为 200 次扫描,并将保存频率限流至
每小时 10 次。
- **生产级 Docker 镜像** —— 在 `node:22-alpine` 上进行多阶段构建,
Next.js standalone 输出,通过
`.github/workflows/` 下的 workflow 部署到 Kubernetes。
## 快速开始
前置条件:Node 22+(本地开发 20+ 版本即可),Yarn 1.x,一个运行中的 MySQL
实例,以及(可选的)一个 Google OAuth client。
```
yarn install
cp env.example .env.local # fill in DATABASE_URL, NEXTAUTH_SECRET, IP_HASH_SALT at minimum
yarn prisma:generate
yarn db:push # provision tables on a fresh DB
yarn dev # http://localhost:3000
```
实现基础登录功能所需的最低环境变量:
- `DATABASE_URL` —— 例如 `mysql://root:password@127.0.0.1:3306/detect`
- `NEXTAUTH_SECRET` —— `openssl rand -base64 32`
- `NEXTAUTH_URL` —— 开发环境中为 `http://localhost:3000`
- `IP_HASH_SALT` —— `openssl rand -base64 32`
可选配置:
- 用于 Google 登录的 `GOOGLE_CLIENT_ID` / `GOOGLE_CLIENT_SECRET`
- 用于真实 magic-link 发送的 `MAILGUN_API_KEY` / `MAILGUN_DOMAIN` / `EMAIL_FROM`
(如果没有这些,链接将被打印到开发服务器控制台)
- 用于通过 ASN / VPN / 代理数据丰富网络探测的 `IPINFO_TOKEN`
完整带有注释的列表请参见 [`env.example`](env.example)。
## 路由
| 路径 | 用途 |
| ----------------- | --------------------------------------------------------- |
| `/` | 营销主页(极光主视觉、功能卡片、FAQ、CTA) |
| `/app` | 检测器 —— 模块列表 + 结果面板 + 概览 |
| `/login` | 独立登录页面(Google / Email / API key) |
| `/scans` | 已登录用户的已保存扫描历史 |
| `/scans/[id]` | 单个已保存扫描详情 |
| `/scans/analytics`| 分布 / 重复 / 时间轴 / 异常 / 对比 |
| `/integrations` | 管理 `det_…` API key(创建 / 吊销 / 操作指南) |
## 项目结构
```
app/
├── (marketing)/ # / — Landing (server-resolved auth state + client UI)
├── app/ # /app — the detector page
├── login/ # /login
├── scans/ # /scans, /scans/[id], /scans/analytics
├── integrations/ # /integrations — API key management
├── api/
│ ├── auth/ # NextAuth route + apiKey-login + tests
│ ├── detect/
│ │ ├── analytics/ # aggregate + pairwise-diff
│ │ ├── network/ # server-side egress probe
│ │ ├── scans/ # save / list / get / delete
│ │ └── uniqueness/ # how many users share this fingerprint hash
│ ├── integration/keys # create / revoke / list API keys
│ └── health/ # liveness probe for k8s
├── opengraph-image.tsx # dynamic OG (per-locale)
├── apple-icon.tsx # dynamic apple-touch icon
├── icon.svg # shield gradient
└── layout.tsx # metadata + theme-init script + LocaleProvider
components/
├── modular-detector.tsx # top-level shell (header + module list + result/overview)
├── detector/ # module-list, result-panel, category filter, state hook
├── result-details/ # one detail view per module (typed switch)
├── overview/ # overview panel + diagnostics export
├── auth/ # AuthGateProvider, login dialog, login form
├── providers/ # SessionProvider wrapper
└── ui/ # shadcn-style primitives + theme/locale toggles
lib/
├── detection-modules/ # 8 module impls + ModuleManager + IP utils + tests
├── risk/ # assess.ts — RiskSignal/score aggregation
├── i18n/ # en.ts / zh.ts + Messages type + locale client/server
├── api/ # withDetectAuth wrapper, scan-payload Zod schema
├── client/ # browser-side scan-api (extractFingerprintInputs, saveScan, lookupUniqueness)
├── server/ # network-probe, IP-hash salt, fingerprint hashing, rate-limit, send-email, analytics
├── persistence/ # SSR-safe localStorage wrappers
├── env.ts # runtime env validation
├── logger.ts # dev-only diagnostic logger
└── prisma.ts # singleton client targeted at .prisma/detect-client
prisma/schema.prisma # User / Account / Session / DetectScan / ApiKey / DetectFingerprintHash
```
## 扫描的完整工作流程
1. 用户在 `/app` 中点击 **Run all**。检测器通过
`ModuleManager.runAllEnabledModules` 遍历已启用的模块 ——
每个模块的失败都会被捕获并隔离,以便其他结果仍能正常显示。
2. 每个模块都会返回一个类型化的 `DetectionResult`(带有 `success | failure`
标记和特定模块的 `data`)。结果面板通过类型安全的 `switch`
渲染每个模块对应的详情组件。
3. `lib/risk/assess.ts` 遍历每个结果,发出带有稳定 ID 的 `RiskSignal`,
并生成 `OverallAssessment`(评分 + 等级 + 计数)。
4. 在 **Save this scan** 时,客户端会提取结构化的 payload + 指纹
哈希(canvas2d / webgl / audio / fontset / UA),并将其 `POST` 到
`/api/detect/scans`。服务器通过 Zod 进行验证,运行自己的网络
探测以记录服务端观测到的 IP / ASN / VPN 标记,并写入一条
`DetectScan` 记录以及多条 `DetectFingerprintHash` 记录。
5. 随后,扫描结果可在 `/scans/[id]` 处查看,它会被纳入分析
聚合,并计入唯一性查询。
## 技术栈
| 层级 | 组件 |
| -------------- | --------------------------------------------------------------------------- |
| 框架 | Next.js 14 (App Router, 到处使用 `force-dynamic`), React 18 |
| 语言 | TypeScript 5, 严格模式 |
| UI | Tailwind CSS 3, 基于 Radix 的 shadcn/ui 原语, Lucide icons, Framer Motion |
| 认证 | NextAuth 4 (Google OAuth + magic-link email) + Prisma adapter |
| 数据 | Prisma 6 → MySQL (自定义 client 输出位于 `.prisma/detect-client`) |
| 校验 | Zod |
| 测试 | Jest 29 + ts-jest + jsdom |
| 构建 / 部署 | 多阶段 Dockerfile, Next.js standalone, Kubernetes manifests |
## 测试
单元测试位于其测试目标旁边的 `__tests__/` 目录中:
```
yarn test # full suite
yarn test path/to/file # single file
yarn test -t "name pattern" # by test-name regex
```
主要内容:
- `lib/detection-modules/__tests__/` —— IP 分类 + mDNS 提取,
模块管理器注册与故障隔离,用于 WebRTC 模块的模拟 `RTCPeerConnection`,
用于浏览器指纹模块的 jsdom-shape 测试,
CDP/自动化信号生成。
- `lib/server/__tests__/analytics.test.ts` —— 分布分桶、重复
分组、异常评分、两两相似度计算。
- `app/api/detect/scans/__tests__` —— POST 保存(校验、速率限制、
幂等性、修剪)+ GET 列表 + DELETE 单条记录。
- `app/api/integration/keys/__tests__` —— 结合模式限制的创建 / 吊销 / 列表
(API-key 会话无法生成其他 API key)。
- `app/api/auth/__tests__` —— apiKey-login 路由(CSRF、格式检查、已吊销 /
过期处理、last-used 更新)。
Lint + 类型检查:
```
yarn lint
npx tsc --noEmit
```
## 部署
包含的 `Dockerfile` 会基于
`node:22-alpine` 生成 Next.js standalone 镜像。生产环境变量通过 Kubernetes Secret 注入 —— 占位符
值在构建时已写入,因此运行时不需要 `SKIP_ENV_VALIDATION`。一个 `prisma db push`
Job 会在发布前运行 schema 更新。完整的镜像构建 → 迁移 → 发布
流水线请参见 `.github/workflows/deploy-tke.yml`。
## 计费与订阅
这个开源版本没有付费墙。保存功能仅受 `lib/server/rate-limit.ts` 中的进程内
用户级速率限制器控制(每小时 10 次保存),并且历史记录
保留时间不受限制。
## 鸣谢
- **[Verdent](https://www.verdent.ai/?id=701236)** —— 用于端到端构建此项目的
智能编码助手。
- **[NextAuth](https://next-auth.js.org/)** —— 身份验证基础设施。
- **[Prisma](https://www.prisma.io/)** —— schema、迁移及生成的 client。
- **[shadcn/ui](https://ui.shadcn.com/)** + **[Radix UI](https://www.radix-ui.com/)** ——
此 UI 所基于的无障碍原语。
- **[Tailwind CSS](https://tailwindcss.com/)** —— 样式系统。
- **[ipinfo.io](https://ipinfo.io/)** —— 网络探测所使用的免费 ASN / VPN 数据。
- **[Mailgun](https://www.mailgun.com/)** —— 生产环境中的 magic-link 邮件发送服务。
## License
参见 [LICENSE](LICENSE)。标签:Prisma, React, Syscalls, WebRTC, 子域名突变, 浏览器指纹, 自动化攻击, 请求拦截, 隐私检测, 风险评分