Skip to content

feat: 在连接列表展示目标 IP 归属地(集成 nali 离线数据库)#117

Open
yu1745 wants to merge 1 commit into
MetaCubeX:masterfrom
yu1745:feat/ip-geolocation
Open

feat: 在连接列表展示目标 IP 归属地(集成 nali 离线数据库)#117
yu1745 wants to merge 1 commit into
MetaCubeX:masterfrom
yu1745:feat/ip-geolocation

Conversation

@yu1745

@yu1745 yu1745 commented Jun 5, 2026

Copy link
Copy Markdown

这个 PR 干了什么

Connections 页的每条连接现在会在 Destination IP 列右侧多一个 Location 列,显示该目标 IP 的归属地(例如 中国|江苏省|南京市|中国电信|CNUnited States|California|Google LLC|US 等)。点开连接详情弹窗也能看到 Destination LocationSource Location 两行。CDN 库的解析函数(lookupCdn)也加载好了,后续在 proxies 页接上即可,本 PR 不动它。

为什么需要

  • 操作员看到一堆陌生目标 IP 时,第一反应就是"这连到哪了?",不希望再复制粘贴到第三方查询网站
  • 离线数据库让 dashboard 完全自给自足,不向外部泄露连接元数据

改了什么

  • src/lib/geoip/{xdb,qqwry,zxipv6,cdn}.ts — 4 个 TS 写的离线 DB reader,从 Go 的 zu1k/nali 移植过来。每个 reader 自包含、200-250 行
  • src/api/geoip.ts — 上层包装:init() 异步加载、lookupIp(ip) 同步查 + LRU 缓存、还有独立的 lookupCdn(host)main.tsx 启动时并行调 init(),加载完前 lookupIp 返回 '',表格显示
  • scripts/fetch-geoip-dbs.ts — build 时下载脚本。从各 DB 官方源拉下来,自动把 zxinc 7z 包里的协议 txt 抽出来,再生成 assets/geoip/NOTICE.md 列出每个 DB 的 SPDX、版权、限制
  • src/lib/buffer-polyfill.ts — 把 buffer npm 包的 Buffer 挂到 globalThis 上,否则 iconv-lite 依赖的 safer-buffer 在浏览器 bundle 里 import 时就会崩
  • GEOIP.md — 集成文档:怎么 fetch、为什么 build 时、合规说明(重点讲 qqwry 的个人使用、zxinc 的非商业)、如何彻底关闭

怎么用

首次克隆后:
```
pnpm fetch:geoip # ~10s,下载 ~38 MB 到 assets/geoip/
pnpm dev
```
之后想更新 DB 重跑 pnpm fetch:geoip 就行。

Build / CI

  • DB 进 git(assets/geoip/ 已 gitignore)。CI runner 需要在 pnpm build 之前先跑 pnpm fetch:geoip,否则产出的 build 不会有 Location 列
  • 脚本每个下载重试 3 次,失败时清掉半成品 .part。zxinc 偶尔半路 RST,其他三个源稳定
  • 新增运行时依赖:iconv-litejs-yamlbuffer。新增 dev 依赖:tsx(只 fetch-geoip-dbs.ts 用,进不了 browser bundle)

协议 / 合规(麻烦重点 review)

  • ip2region(Apache-2.0)和 SukkaLab/cdn(MIT)按归属分发的标准做法走,链接在 NOTICE.md
  • qqwry 是 CZ88.NET 的纯真 IP 库:仅限个人使用、不得倒卖、不得修改数据。Yacd-meta 是开源免费的,个人自用部署没问题。如果要做付费产品/服务,建议先把 qqwry.dat 移出 bundle(GEOIP.md 里有步骤)
  • zxinc 的 ZX IPv6 数据库是非商业许可,协议 §1 明确要求每次分发都必须随附完整未改动的协议文档。fetch 脚本会把 版权声明.txt使用说明.txt格式详解-ipdb.txt 三个文件抽到 assets/geoip/zxinc-license/ 里,再分发时不要删

相比 nali Go 版(运行时下载到 ~/.local/share/nali/),我们只是把同一组下载挪到 build 阶段,没更坏

已知限制

  • zxinc 在 2021-05-11 之后停止免费更新,bundle 里就是那个快照
  • qqwry 是 GBK 输出,如果用户浏览器缺 CJK fallback 字体可能显示成口口。现代浏览器没事
  • Location 列写死 220px,长的中文归属地会被截断;hover 显示完整 tooltip
  • CDN reader 已加载但 UI 还没接,proxies 页以后可以接

这次 PR 不动的事

  • Clash 自己的 geoip/geosite 升级(Config 页那个 POST /upgrade/geo),那是 Clash 自己的 DB,跟我们这套无关
  • proxies 页的 CDN 显示(之后可以接,本 PR 范围外)
  • 没加 config flag 关闭这功能。要关掉按 GEOIP.md "Removing the feature" 步骤来

怎么验

手动:

  • 接个 Clash 实例,让它跑出几个连接,目标 IP 包括 8.8.8.8、1.0.1.0、114.114.114.114、2400:3200::1
  • 进 Connections 页,几秒内 Location 列从 变成具体归属地
  • 鼠标悬停长字符串,tooltip 弹出完整内容
  • 点任一连接,弹窗里看 Destination Location / Source Location

回归:

  • 其他列(process / rule / chains 等)布局不变
  • useConnectionsStream 的 WebSocket 流程没动

Connections 页每行新增 Location 列,渲染目标 IP 的归属地。
点开连接详情还能看到 Destination/Source Location。

数据源是从 Go 的 zu1k/nali 移植过来的 4 个离线 DB:
- ip2region.xdb (Apache-2.0)
- qqwry.dat (CZ88 纯真,个人使用)
- zxipv6wry.db (ZX 非商业,协议要求随附 协议 txt)
- cdn.yml (SukkaLab MIT)

DB 通过 pnpm fetch:geoip 在 build 时下载到 assets/geoip/,
该目录已 gitignore。zxinc 的协议 txt 会被自动抽到
assets/geoip/zxinc-license/ 满足 §1 的再分发要求。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@yu1745

yu1745 commented Jun 5, 2026

Copy link
Copy Markdown
Author
image 效果如图,之所以没做纯前端fetch数据库是因为四个数据库里有两个是前端没法直接fetch拿到的,所以做成了构建时作为assets跟随。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant