commit3296/adler
GitHub: commit3296/adler
Adler 是一款用 Rust 实现的跨约 2,600 个站点进行 OSINT 用户名搜索的工具,通过浏览器后端、TLS 指纹模拟和多代理策略攻克受保护的难访问站点,并提供带证据和置信度的可靠判定结果。
Stars: 3 | Forks: 1
# Adler
使用 Rust 跨越约 2,600 个内置站点条目进行 OSINT 用户名搜索。提供可靠的判定结果,旨在攻克那些难以访问的网站 —— 包括受 Cloudflare 保护的、带有 TLS 指纹验证的、受地理位置限制的以及需要登录的站点。
## 文档
- 📖 [**adler-docs**](https://adler-docs.pages.dev/) — 用户手册:安装、访问引擎、Web UI、嵌入、常见问题。
- 🦀 [docs.rs/adler-core](https://docs.rs/adler-core) — Rust API 参考。
- 🗺️ [PLAN.md](PLAN.md) — 路线图以及访问引擎背后的设计。
本 README 涵盖了电梯演讲式介绍(对比表、检测率数据)以及安装 / 快速入门;更深入的内容位于文档网站上,以便其能独立于 crate 发布进行演进。
## Adler 对比
开源 OSINT 操作员实际会考虑使用的用户名搜索工具,在这些站点发起反抗的关键维度上的对比:
| | [Sherlock][cmp-s] | [Maigret][cmp-m] | [Blackbird][cmp-b] | [Snoop][cmp-sn] | **Adler** |
| ---------------------------- | :---: | :---: | :---: | :---: | :---: |
| 大约支持站点数 | 400 | 3,000 | 600 | 5,400 | 2,600 [^cmp-1] |
| 判定模型 | Found / NotFound | Found / NotFound | Found / NotFound | Found / NotFound | **Found / NotFound / Uncertain(reason)** |
| 机器人保护的站点 (Ko-Fi, CodePen, …) | — | — | — | — | **通过 `--browser-backend` 使用操作员浏览器后端** |
| TLS 指纹拦截 | — | — | — | — | **通过 `--features impersonate` 模拟 Chrome 134 握手** |
| 代理路由 | 一个全局 | 一个全局 + Tor + I2P | — | — | 通过 `--proxy-pool` 使用一个全局**或**按站点策略 |
| Cookies / 会话 | — | 全局 `cookies.txt` | — | — | **通过 `--sessions` 使用按站点的命名会话** |
| 注册表自我修复 | — | — | — | — | **`--doctor --fix` 对比响应,提出新的签名** |
| Web UI | — | 是 (结果图表、报告) | — | — | `--web` — 实时 SSE 流式传输 SolidJS SPA + JSON API |
| 输出格式 | text / CSV / XLSX / JSON | text / JSON / CSV / HTML / PDF / XMind / D3 | text / CSV / PDF | text / CSV / HTML | text / JSON / NDJSON / CSV / HTML |
| 可嵌入的库 | — | 是 (Python async) | — | — | crates.io 上的 `adler-core` (Rust) |
| 运行时 / 打包 | Python | Python | Python | Python | **Rust — 单一静态二进制文件,`cargo binstall`** |
[^cmp-1]: 主注册表中有 1,900 个条目,加上默认开启的 WhatsMyName 补充包中的 675 个;参见 [*站点注册表*](#site-registry)。
**Adler 的核心论点:提供可靠的判定结果,并对重要的站点实现访问。** 对于那些受 Cloudflare 保护、带有 TLS 指纹验证、受地理位置限制或需要登录的站点,仅使用普通 Python HTTP 工具得出的 `NotFound`(未找到)结果,往往只意味着“我在第一道墙前就放弃了”。当 Adler 无法验证时,它会报告 `Uncertain(reason)`,并提供了你可以选择启用的预配置访问路径 —— 无头浏览器、Chrome 握手模拟、按站点的地理 / IP 类型出口、操作员提供的会话。我们不解决 CAPTCHA 或绕过人工验证(参见 [*道德与负责任的使用*](#ethics--responsible-use))。
## 证据、置信度与报告
近期的 Adler 构建携带的不仅仅是 Found/NotFound 判定。JSON、Web/API、MCP 和调查报告层面可以展示结果背后的检测证据、标准化的个人资料证据(如显示名称或外部链接)、带有机器可读原因的置信度评分,以及当多个找到的个人资料共享强有力的结构化证据时生成确定性身份聚类候选。
`adler --avatar-hash` 是一个可选的富化步骤,适用于适合获取外部头像的情况。它会在限制大小/类型/超时检查的情况下对提取的头像图像进行哈希处理,并仅存储标准化后的哈希;原始图像字节不会被持久化。头像哈希是聚类的辅助证据,而非独立的身份证明。
使用 `adler --report-scan
` 获取 Markdown 调查报告;如果其他工具需要直接消费报告模型,请使用 `adler --report-scan --report-format json`;或者使用 `adler --report-scan --report-format html > report.html` 生成一个独立、自包含的本地案例文件。这些报告派生自本地扫描产物;关于存储的内容以及如何处理扫描 ID、证据、聚类和报告文件,请参见 [隐私与保留](docs/privacy-retention.md)。
## 检测率
召回率取决于你的扫描位置。最后一次公开的、同等条件下的测量结果来自于 2026-05-26 针对 v0.3.x 注册表(411 个站点)的 `--doctor` 运行:
| 扫描来源 | 找到已知存在账号的网站数量 | 召回率 |
| --- | ---: | ---: |
| 数据中心 IP (Hetzner / Leaseweb DE) | 282 / 411 | 68.6% |
| 美国住宅代理池 (DECODO) | **305 / 411** | **74.2%** |
住宅 IP 带来的提升是显著的:约 40 个站点在 `Uncertain`(数据中心)和 `Found`(住宅)之间改变了判定结果 —— 大多数是受 Cloudflare 保护或受地理限制的(俄罗斯区段,以及像 Reddit、Imgur、Patreon 等平台)。剩下约 26% 的失败情况大致分为:
- **被标记为 `bot-protected` 的机器人保护站点**(Ko-Fi、CodePen、DeviantArt 以及当今类似平台) —— 这些站点会对普通的 HTTP 请求提供 JS 登录墙;干净的 IP 无济于事,你需要一个浏览器后端。
使用 `--exclude-tag bot-protected` 排除它们。
- **陈旧的从 Sherlock 导入的 `known_present` 账号**,这些账号在实时站点上已不存在。`--doctor --suggest-known-present` 工具(v0.4.0 中的新功能)会探测一小部分候选池(站点的品牌名称,加上 `torvalds` / `octocat` / `admin` / …),并在找到实时账号的站点打印出可直接粘贴的片段。在最近一次扫描中,发现了 19 个可修复的条目;剩余的占位符需要贡献者找到的候选者或通过 `--doctor --fix` 进行更深层的修复。
- **其检测规则对*每个*用户名都会触发的站点** —— 这是信号修复范畴,而非用户名修复。`--doctor --fix` 会对比响应并提出更严格的信号。
- **对于未经身份验证的请求根本无法可靠区分找到与未找到的站点** —— 这些已被调查,而不是作为误报条目发布:Reddit 现在需要可选的 OAuth 会话,Pinterest 和 TikTok 使用公共 oEmbed 端点,而 Threads 仍处于搁置状态。有关具体的失败模式以及如何解除每个站点的限制,请参见 issues
[#11–#14](https://github.com/commit3296/adler/issues?q=is%3Aissue+label%3A%22help+wanted%22)。
你可以自己运行相同的检查:`adler --doctor`(使用你当前的 IP)或 `adler --doctor --proxy `(通过你自己的代理)。使用 `--browser-backend browserbase` 时,doctor 的 `--fix` 模式会通过真实的 Chrome 会话路由受机器人保护的站点,因此差异对比会看到真实的个人资料页面,而不是两个一模一样的登录墙。配合 `--suggest-known-present`,你会为每个可修复的站点获得一个 OVERRIDES 块。
## Crates
| Crate | 类型 | 用途 |
| ------------- | ---- | ---------------------------------------------------- |
| `adler-core` | lib | 检测引擎、站点注册表、执行器。 |
| `adler-server`| lib | HTTP API + SSE 流式传输 + 扫描持久化;通过 `rust-embed` 嵌入 SolidJS Web UI。 |
| `adler-mcp` | lib | Model Context Protocol 服务器 (`rmcp 1.7`);通过 stdio + Streamable HTTP+SSE 向 AI 代理暴露 OSINT 层面。 |
| `adler-cli` | bin | `adler` 命令行界面;`--web` 在进程内启动嵌入式服务器 + UI;`--mcp` / `--mcp-http` 启动 MCP 服务器。 |
## 安装
从 crates.io 安装(本地编译,约 1–2 分钟):
```
cargo install adler-cli
```
从 GitHub release 下载预构建的二进制文件(即时完成,无需编译):
```
cargo binstall adler-cli # https://github.com/cargo-bins/cargo-binstall
```
从源码构建:
```
git clone https://github.com/commit3296/adler.git
cd adler
cargo install --path adler-cli
```
要求 Rust ≥ 1.85。安装的二进制文件名为 `adler`。库
([`adler-core`](https://crates.io/crates/adler-core))单独发布,
用于将引擎嵌入到你自己的工具中 —— 请参阅下面的
[*库*](#library) 部分。
### 验证 release 产物
附加到 GitHub Release 的每个平台压缩包都使用
[Sigstore cosign](https://github.com/sigstore/cosign) 和 GitHub Actions OIDC 身份进行了签名 —— 不保留长期密钥,签名证书是短期的,且与生成它的确切工作流绑定(可在 [Rekor](https://search.sigstore.dev/)
透明度日志中查看)。签名 (`.sig`) 和证书 (`.pem`) 会与每个压缩包一起上传到发布页面。
```
TAG=v0.11.3 # or whichever release
ARCHIVE=adler-x86_64-unknown-linux-gnu.tar.gz
# 从 release 拉取 archive 及其 signature 和 certificate。
gh release download "$TAG" --repo commit3296/adler \
--pattern "$ARCHIVE" --pattern "$ARCHIVE.sig" --pattern "$ARCHIVE.pem"
# 验证 signature 是否绑定到此 repo 的 release.yml workflow。
cosign verify-blob \
--certificate "$ARCHIVE.pem" \
--signature "$ARCHIVE.sig" \
--certificate-identity-regexp '^https://github\.com/commit3296/adler/\.github/workflows/release\.yml@refs/tags/v[0-9]+\.[0-9]+\.[0-9]+' \
--certificate-oidc-issuer 'https://token.actions.githubusercontent.com' \
"$ARCHIVE"
```
成功的验证会打印 `Verified OK`。identity-regex 将签名者固定在*此*仓库的 SemVer 标签下的 `release.yml` —— 在不同工作流下上传的伪造压缩包将无法通过验证。
## 安全态势
Adler 仅通过 PR 在公开仓库中推进强化路径:CI、CodeQL、cargo-audit、OpenSSF Scorecard、Dependabot 安全更新、带有推送保护的密钥扫描,以及 cargo-fuzz 种子目标全部在 GitHub 上运行。发布工作流使用 Sigstore OIDC 对产物进行签名,安全敏感型自动化通过 `.github/CODEOWNERS` 进行所有权管理。
工作流 actions 和 Docker 基础镜像被固定到具体的 commit/digest 输入。通过依赖 PR 或遵循 [安全操作](docs/security-operations.md) 来更新这些固定版本;切勿在日常维护中将它们改回浮动标签。
## 构建与运行
```
cargo build --workspace
cargo run -p adler-cli -- alice
```
日志记录由 `ADLER_LOG` 环境变量控制(默认为 `adler=info`):
```
ADLER_LOG=adler=debug cargo run -p adler-cli -- alice
```
## 使用方法
`adler ` 扫描内置注册表;其他所有内容都是配置项。默认情况下,文本输出显示 Found 和 Uncertain,并隐藏 NotFound —— 传递 `--all` 获取完整列表。结果在解析时会流式传输到终端;管道输出将被收集并排序。退出代码:`0` 找到,`1` 未找到,`2` 错误。
以下是一些最常见的配置项:
```
adler --tag dev,social alice # filter by tags
adler --top 50 alice # popularity rank <= 50
adler --format ndjson alice # one JSON object per line
adler --proxy socks5://host:1080 alice # single proxy for everything
adler --browser-backend local alice # bot-protected sites via Chrome
adler --input users.txt # batch many usernames
adler --watch alice # diff vs last run
```
→ 完整的标志参考,按意图分组(过滤 / 输出 / 网络与会话 / 浏览器与缓存 / 批处理与富化),位于 [**使用方法**](https://adler-docs.pages.dev/usage/) 页面。
`adler --help` 列出了每个标志及其简短说明;文档页面则补充了更宏观的背景信息。
### 过滤契约
所有扫描层面都使用相同的注册表过滤语义。名称略有不同,因为 CLI 标志是 kebab-case,HTTP JSON 是 snake_case,而 MCP 暴露的是对代理友好的 JSON 参数:
| 含义 | CLI | Web / HTTP API | MCP |
| --- | --- | --- | --- |
| 包含站点名称中带有任意关键词的站点,不区分大小写 | `--only NAME` | `only: string[]` | `only: string[]` |
| 排除站点名称中带有任意关键词的站点,不区分大小写 | `--exclude NAME` | `exclude: string[]` | `exclude: string[]` |
| 包含带有任意标签的站点,不区分大小写精确匹配 | `--tag TAG` | `tag: string[]` | `tag: string[]` |
| 排除带有任意标签的站点 | `--exclude-tag TAG` | `exclude_tag: string[]` | `exclude_tag string[]` |
| 包含成人内容网站 | `--nsfw` | `nsfw: boolean` | `include_nsfw: boolean` |
| 保留排名满足 `popularity <= N` 的站点;丢弃未排名的站点 | `--top N` | `top: number` | `top: number` |
| 将 Web/服务器扫描限制为 `--proxy-pool` 中指定的出口 | n/a | `egress_names: string[]` | n/a |
空数组 / 省略的值表示该维度“无过滤”。
被禁用的站点永远不会被扫描。`nsfw` 站点默认是隐藏的,但请求 `--tag nsfw` / `tag: ["nsfw"]` 也是明确的开启行为。多个包含维度使用 AND 组合;在单个维度内,关键词使用 OR 组合。
## Web UI
`adler --web` 启动一个小型进程内 HTTP 服务器,并从同一个二进制文件中提供 SolidJS SPA —— 包括实时 SSE 流式扫描、持久化的历史记录、与早期运行结果进行并排差异对比(带有用于选择*与哪个*历史扫描进行对比的选择器)、只读访问引擎面板、加载了 `--proxy-pool` 时的按扫描出口子集选择,以及一个单次/批处理标签页对,这样你就可以将用户名列表粘贴到主输入框中,看着它们逐一排队处理。服务器持久层还通过 `/api/scans/timeline/{username}` 为首次发现、消失、重新出现以及证据发生变化的资料构建时间线事件;UI/MCP 的展示可能会在后续版本中加入。
```
adler --web # http://127.0.0.1:8080
adler --web --web-bind 0.0.0.0:9000 # listen on all interfaces, custom port
```
→ [**Web UI**](https://adler-docs.pages.dev/web-ui/) 页面
涵盖了完整的功能集、`/api/*` 层面以及部署说明(SPA 通过 `rust-embed` 嵌入到二进制文件中;在 `adler-server/web/` 中使用 `npm ci && npm run build` 从源码重新构建)。
## MCP 服务器
Adler 通过 [Model Context Protocol](https://modelcontextprotocol.io/) 向 AI 助手暴露其 OSINT 接口。代理可以调用的七种**工具**(`list_sites`、带流式进度的 `scan_username`、`scan_batch`、`doctor_check`、`get_scan_history`、`diff_scans`、`get_investigation_report`),
它可以浏览的九种**资源**(`adler://registry/{sites,tags, disabled}`、`adler://scans/recent`、`adler://watchlists/default`、`adler://scans/{id}` / `adler://scans/{from}/diff/{to}` / `adler://timelines/{username}` / `adler://reports/{id}` 模板),
以及三个带有模板化 OSINT 工作流的**提示词**(`investigate_username`、`audit_registry_health`、`correlate_accounts`)。支持两种传输方式 —— 根据代理的运行方式选择合适的一种。
```
adler --mcp # stdio: Claude Desktop / Cursor / local agents
adler --mcp-http 127.0.0.1:8766 # HTTP+SSE: remote agents, mounted at /mcp
```
HTTP 传输方式开箱即用地继承了 `rmcp` 的环回 `allowed_hosts` DNS 重绑定防护;非环回绑定会在没有身份验证的情况下暴露 API,因此请仅在受信任的网络中进行此操作。MCP 扫描工具上的 `top` 过滤器是一个流行度排名上限(`popularity <= top`),而不是“最多返回 N 个结果”;设置该值时,未排名的站点会被排除。在 `initialize` 时发送的 `instructions` 块重申了项目的道德界限(仅限授权的安全测试 / OSINT 研究 / 防御性工作;禁止骚扰、人肉搜索或未经授权的监视),以便代理在首次查看服务器时就能明确哪些在范围内。
→ [**使用方法**](https://adler-docs.pages.dev/usage/#mcp-server)
页面列出了每个工具 / 资源 / 提示词及其参数和返回结构。`adler-mcp/examples/` 提供了两个可直接运行的探测脚本(stdio + HTTP),它们同时也作为最小 MCP 客户端的参考实现。
## 隐私与保留
Adler 仅在需要重用的层面存储本地产物:
一次性扫描可能会使用结果缓存,`--watch` 会保留先前找到的账户快照,而 `adler --web` 会将完成的扫描 JSON 写入 `$XDG_CACHE_HOME/adler/scans/`(回退到 `$HOME/.cache/adler/scans/`)。MCP 的历史记录、差异对比、时间线和报告层面会读取同一个 Web 历史目录,但它们本身不会创建扫描历史记录。
对于不应触及结果缓存的一次性扫描,请使用 `--no-cache`;使用 `adler --cache-clear` 移除缓存文件;为一次性的 Web/MCP 会话设置临时的 `XDG_CACHE_HOME`;如果历史记录需要指定位置,请使用 `--scans-dir`。非环回的 `--web-bind` 和 `--mcp-http` 在没有 Adler 提供的身份验证的情况下暴露历史记录和扫描 API;请在它们前面配置你自己的访问控制。
→ 详细信息位于 [docs/privacy-retention.md](docs/privacy-retention.md)。
## 访问引擎
Adler 为普通 HTTP 客户端无法访问的站点提供了一个传输阶梯 —— 这正是它在注册表中的高难度子集上得分领先于 Sherlock / Maigret 的全部原因:
- **浏览器后端**(`--browser-backend local` / `browserbase` / `flaresolverr`) —— 为带有 `bot-protected` 标签的站点(Ko-Fi、CodePen、DeviantArt 以及当今类似平台)提供由操作员提供的浏览器执行。受 `--browser-budget` 限制,因此配置错误的标志不会耗尽配额。
除非渲染后的页面暴露了严格的个人资料证据,否则验证质询页面仍将被归类为 `Uncertain(reason)`。
- **TLS 指纹模拟**(`cargo install --features impersonate`) —— 为带有 `protection: tls-fingerprint` 标签的站点提供进程内的 Chrome 134 BoringSSL 握手。比真实浏览器成本低得多。
- **出口池**(`--proxy-pool `) —— 按站点的地理 / IP 类型路由。具有 `access` 策略的站点会选择匹配的代理;没有该策略的站点保留在默认出口上。`region:XX` 标签会自动填充一个*软性* `prefer_geo`(自 v0.12 起),因此当配置了匹配的出口时,685 个带有区域标签的站点会获得召回率提升,并在没有配置时回退到默认值 —— 不会出现硬性的 `Uncertain(GeoUnavailable)`。
- **会话**(`--sessions `) —— 操作员为登录受限的站点提供的 cookies / tokens。按站点的 `[name]` 表;值会从日志中打码隐藏。Reddit 受会话限制:请手动提供 `[reddit] Authorization = "Bearer "`,或者设置 `REDDIT_CLIENT_ID` / `REDDIT_CLIENT_SECRET`,Adler 将为 `reddit` 会话获取仅限应用的 OAuth bearer token。如果不提供这些可选凭证之一,Adler 将报告 `session_required`,而不是进行匿名探测。
- **自动升级**(`--escalation-budget N` / `--no-escalation`) —— 当低成本路径返回 `Uncertain(cloudflare_challenge | rate_limited)` 时,路由器会自动通过浏览器后端重试。受其自身的预算限制。结果会带有 `transport` 和 `escalations` 遥测数据,以便清楚每个判定是由哪条路径产生的。`adler --doctor --suggest-protection`(自 v0.13 起)会读取跨运行的遥测数据,并将持续升级的站点标记为预先添加 `protection: cloudflare` 的候选对象。
- **浏览器矩阵诊断**(`adler --doctor --browser-matrix`) —— 通过配置的访问路径以及原始/无浏览器基线,对比受保护站点的主要 `known_present` 用户。使用它来判断 `local`、`browserbase`、`flaresolverr`、出口或会话是否真正改善了检测效果。
→ 包含 TOML 格式、防护机制和权衡的完整指南位于 [**访问引擎**](https://adler-docs.pages.dev/access-engine/)。
## 库
`adler-core` 是驱动 CLI 的运行时无关引擎,单独发布在 [crates.io](https://crates.io/crates/adler-core) 上,
用于嵌入到你自己的 Rust 工具中 —— 比如检查用户名的 Discord 机器人、标记跨观察列表中暴露身份的安全工具,或者断言某个名称未在其他地方被占用的 CI 门禁。
核心 crate 还暴露了 `WatchlistConfig`,用于建模被监视的用户名、别名和站点/标签范围,而无需将该模型耦合到 CLI 循环、Web 状态或调度程序中。当调用者需要重复扫描策略时,可以添加 `ScanSchedule`,同时将计时器和任务队列保留在其自己的运行时中。
```
[dependencies]
adler-core = "0.10"
tokio = { version = "1", features = ["macros", "rt-multi-thread"] }
```
→ 最小可用示例、重要的 `ClientBuilder` 配置项以及各版本的破坏性变更日志位于 [**嵌入**](https://adler-docs.pages.dev/embedding/) 页面。完整的 API 参考位于 [docs.rs/adler-core](https://docs.rs/adler-core)。
## 站点注册表
默认注册表(`adler-core/data/sites.json`,约 2.5k 个站点)基于 MIT 许可证的上游数据生成 —— Sherlock + Maigret + 可选的 WhatsMyName 部分(CC BY-SA 4.0;如果在仅根据 MIT 许可证重新分发扫描输出时需要丢弃它,请传递 `--no-wmn`)。导入的检测是**未经验证的** —— `adler --doctor` 会验证每个信号,`--doctor --fix` 会提出修正建议,而 `--doctor --fix --apply --sites `(自 v0.12 起)会通过原子的同级 `*.tmp` 重写将它们直接修补到 JSON 文件中。
→ 详细的起源、schema、信号模型和 doctor 工作流位于 [**站点注册表**](https://adler-docs.pages.dev/site-registry/)。
## 故障排除
常见问题(“为什么一切都是 Uncertain?”、“为什么 Adler 找到的账户比 Sherlock 少?”、“我该如何扫描 Instagram?”、……)在文档网站的 [**常见问题**](https://adler-docs.pages.dev/faq/) 中得到了解答。
有关面向 CI / 贡献者的命令(`cargo fmt`、`cargo clippy`、`cargo test`),请参见 [CONTRIBUTING.md](CONTRIBUTING.md)。
## 道德与负责任的使用
Adler 聚合了公开可访问的个人资料 URL,但聚合使得入侵变得容易 —— 请负责任地使用它。
**预期用途:** 检查你自己的账户;授权的渗透测试和漏洞赏金任务;安全研究;以及具有合法依据的 OSINT 调查。**请勿**使用 Adler 在未经授权的情况下跟踪、骚扰、人肉搜索或监视他人,或对个人进行大规模定向攻击。
**检测,绝不规避。** Adler 将反机器人响应(速率限制、Cloudflare 验证质询、CAPTCHA)报告为 `Uncertain` —— 它不会破解验证码或绕过访问控制。它按主机进行速率限制,支持 `--max-rps` 和 `--respect-robots`,并写入一个可选的 `--audit-log` 来记录每个请求。
请参见 [SECURITY.md](SECURITY.md) 和 [CODE_OF_CONDUCT.md](CODE_OF_CONDUCT.md)。
## 许可证
Adler **代码**采用 [MIT 许可证](LICENSE) 授权。
默认的站点注册表(`adler-core/data/sites.json`)也采用 MIT 许可证 —— 它派生自 Sherlock 项目 (MIT) 和 Maigret 项目 (MIT)。有关署名,请参见该文件的 `_comment` 头部和 `scripts/` 中相应的导入器脚本。
补充注册表(`adler-core/data/sites_wmn.json`,默认包含;可使用 `adler --no-wmn` 选择退出)派生自 WhatsMyName,并采用 [CC BY-SA 4.0](LICENSE-CC-BY-SA-4.0) 许可证授权。Adler 的 MIT 许可证不涵盖此文件;下游重新分发必须保留署名和对衍生数据的 `ShareAlike`(相同方式共享)义务。
标签:ESC4, OSINT, Rust, 可视化界面, 用户名枚举, 网络流量审计, 通知系统