rallisf1/hesperida
GitHub: rallisf1/hesperida
一个自托管的网站扫描器,集成 SEO、可访问性与漏洞扫描,帮助统一评估网站质量与安全。
Stars: 2 | Forks: 1

# Hesperida
一个自托管的网站扫描器,展示人类和机器人如何看待您的网站和网络应用程序。
## 功能
### 扫描工具
| **类型** | **依赖项** | **状态** | **描述** |
|-------------|---------------------------------|------------|-----------------------------------------------------------------------------------|
| 域名 | [rdapper](https://www.npmjs.com/package/rdapper), [whois](https://github.com/rfc1036/whois), [subfinder](https://github.com/projectdiscovery/subfinder) | ✅ | 获取基本域名信息(例如注册商、注册/到期日期等)& 记录 |
| 探测 | [httpx](https://github.com/projectdiscovery/httpx) | ✅ | 获取 Web 服务器和科技栈的基本信息 |
| SEO | [@seomator/seo-audit](https://www.npmjs.com/package/@seomator/seo-audit), [playwright](https://github.com/microsoft/playwright) | ✅ | 基于 251 条规则、20 个类别进行 TypeScript 基础的 SEO 审计和评分 |
| SSL | - | ✅ | 使用 `node:tls` 获取基本证书信息 |
| WCAG | [@axe-core/playwright](https://www.npmjs.com/package/@axe-core/playwright), [playwright](https://github.com/microsoft/playwright) | ✅ | 检查 Web 可访问性规则(同时会截取全屏截图) |
| Whois | [whois](https://github.com/rfc1036/whois) | ✅ | 获取 IP 的 Whois 信息 |
| 安全 | [nuclei](https://github.com/projectdiscovery/nuclei), [wapiti](https://github.com/wapiti-scanner/wapiti), [nikto](https://github.com/sullo/nikto) | ✅ | 标准漏洞扫描 |
| 压力测试 | [vegeta](https://github.com/tsenart/vegeta) | ✅ | HTTP 负载测试 |
### 仪表板
一个 Sveltekit 仪表板处于测试阶段。主要功能包括:
1. 用户/网站/任务的 CRUD 操作
2. 网站验证说明和验证检查
3. 查看扫描结果
### API
所有仪表板功能均可通过 [OpenAPI](http://localhost:3000/api) 使用。
### 警报与 Webhook
[Apprise](https://github.com/caronc/apprise) 现已集成用于通知消息和邮件。
邀请/忘记流程使用 `NOTIFICATION_EMAIL_TARGET_TEMPLATE` 作为投递目标。
用户级别的通知目标存储在 `users.notification_targets` 中,用于应用内管理的渠道。
## 技术栈
- JavaScript 运行时:[Node.js](https://github.com/nodejs/node) & [Bun](https://github.com/oven-sh/bun)
- 容器化与部署:[Docker](https://github.com/docker) & [dockerode](https://github.com/apocas/dockerode)
- 数据库:[SurrealDB](https://github.com/surrealdb/)
## 如何使用
1. 下载,亦即 `git clone https://github.com/rallisf1/hesperida.git`
2. `cp .env.example .env` 并编辑您的信息
3. 启动:
- 使用自托管数据库
`docker compose --profile aio up -d`
- 使用 SurrealDB SaaS
`docker compose run --rm db-init && docker compose --profile backend up -d`
- 开发配置(仅包含数据库、db-init 和编排器)
`docker compose --profile dev up -d`
4. (可选)可使用 `docker compose --profile tools build` 预先构建工具容器。如果跳过此步骤,首次运行将需要几分钟。
5. 打开 `https://localhost:3000`(或根据您的配置)
### 超级用户账户
**邮箱:** hesperida@local.me
**密码:** `SURREAL_PASS` 的值
您可以在之后更改两者
### 更新
1. `docker compose --profile aio down` 停止运行中的容器
2. `git pull` 拉取最新版本
3. `docker compose --profile tools build` 重新构建工具
4. `docker compose build orchestrator` 重新构建编排器
5. `docker compose --profile aio up -d` 启动
## 已知缺陷
- 在高并发下任务执行的可靠性仍需调整。已知原因包括:
1. RocksDB 上的文档锁可能与高并行工作负载冲突(例如多个 `whois` 任务)
2. 资源不足,请升级主机
- 尚未为 `job_queue` 设置清理定时任务(TODO)
- 如果编排器崩溃,可能会留下孤立容器。当我在容器设置中尝试使用 `AutoRemove: true` 时,容器在完成前就退出了。据我所知这是 Bun 的一个 Bug。这不是大问题,因为它们不会一直运行,但需要为这些容器设置清理定时任务。(TODO)
- `orchestrator` 和 `wcag` 容器在无法连接到数据库时似乎会卡住,因为存在无限重连尝试
## 想法
一些我个人不需要,但对某些用户可能有用的功能。请在 [issues](https://github.com/rallisf1/hesperida/issues) 中查看您需要的条目并点赞首个帖子。不要回复功能请求,除非您有实质性补充。如果尚未创建议题,请新建一个。
### 探测
1. 能够测试表单提交(POST 请求)
2. 能够使用身份验证(登录)
3. 能够检查子页面(又称爬行)
### WCAG
1. 在截图中高亮错误
### SEO
1. 搜索结果排名(与 SerpBear 集成?)
2. 内容检查
- 人工智能生成内容
- 抄袭
- 语法
- 占位符(例如 lorem ipsum)
### 仪表板
1. 公共仪表板(例如与客户/同事共享),尽管 `/jobs/[id]/pdf` 链接是公开的。
2. AI 助手,帮助您修复发现的错误
### API
1. MCP 服务器
2. n8n 节点
### 压力测试
[k6](https://github.com/grafana/k6) 可用于处理复杂工作流(例如登录)。
当前 `stress` 工具选项包括:
- `STRESS_RATE`
- `STRESS_DURATION`
- `STRESS_METHOD`
- `STRESS_TIMEOUT`
- `STRESS_WORKERS`
- `STRESS_MAX_WORKERS`
- `STRESS_HEADERS`
- `STRESS_BODY`
- `STRESS_LATENCY_WARN_MS`
## 硬件要求
资源越多越好,但至少需要:
### 最低配置
- 2 个 CPU 核心 / 4 个线程(又称标准 VPS 上的 4 个 vCores)
- 4GB 内存
- 6GB 可用存储空间(5GB 用于镜像 + 1GB 用于实际数据)
轻量(CLI/Node 工具)和重量(完整浏览器)工具容器之间存在区别,编排器不会运行超过可用 CPU 线程的重型容器。
## 常见问题解答
### `tools` Docker 配置文件中有什么?
这些仅用于开发者测试和预构建,您在生产环境中通过 Docker Compose 运行它们是不必要的。
### 我能将服务部署到不同主机(又称服务器)上吗?
目前,您可以将数据库部署在与编排器不同的主机上,使用 `database` 和 `backend` 配置。
您还可以将 API 和仪表板分别部署。
在 `backend`(又称编排器)与扫描工具之间运行在不同的主机上不在本开源项目的范围内。
### axe-core 不提供评分,您如何计算?
axe-core 为每个规则检查提供影响评级,评分方式如下:
| 影响 | 分数 |
|----------|-------|
| 严重 | 10 |
| 重要 | 7 |
| 中等 | 3 |
| 轻微 | 1 |
总评分百分比公式为 `100 - (pass_score / (pass_score / error_score))`。不适用和未完成的规则检查暂时不评分。
如果您有更好的公式,请提交您的 [问题](https://github.com/rallisf1/hesperida/issues/new)。
### WCAG 结果可靠吗?
在做出此判断之前,我使用了 [WAVE](https://wave.webaim.org/)。与 WAVE 相比,axe-core 的可靠性稍低,但更严格:我检查的所有网站在 axe-core 上都产生了更多错误,但警告少得多。我的结论是,如果 axe-core 中没有错误,WAVE 上也不会有错误。如果您只需要修复 WCAG 错误通过检查),那么您没问题;但如果您的目标是完全符合 WCAG 的 Web 界面,那么这工具不适合您。
### 如何计算安全评分?
每个发现都会根据下表获得一个惩罚分数:
| 影响 | 分数 |
|----------|-------|
| 严重 | 10 |
| 高 | 7 |
| 中等 | 3 |
| 低 | 1 |
然后将所有分数相加,并根据环境变量 `SECURITY_SCORE_THRESHOLD`(默认值为 `400`)计算百分比。如果总分数超过 `400`,则安全评分为 0%(黑客天堂)。如果惩罚分数为 0,则安全评分为 100%(坚不可摧)。数字 `400` 是任意的,基于几次测试。它可能需要根据您的用例或更新(例如更多/新的严重错误变得常见)进行调整。
也就是说,Hesperida 的评分计算可能会因配置和版本而异。因此,在不同实例之间比较分数没有意义。
### 我可以扫描任何网站还是仅限于我自己的网站?
在 v0.4.1 中添加了 DNS / Web 根文件验证流程,因此您只能扫描有权访问其 DNS 区域或 Web 根目录的网站。
验证在每个 `(组, 可注册域名)` 范围内共享,并存储在专用验证记录中。
要验证您的网站,请执行以下操作之一:
- 为 `hesperida.yourdomain.com` 添加一个 TXT DNS 记录,其值为 `verification_code`,或
- 在您的 Web 根目录中添加一个名为 `hesperida-${verification_code}.txt`(空)的文件
然后通过仪表板或使用 `/api/v1/websites/[id]/verify` API 端点进行验证。
### 我可以在 CI/CD 流水线中使用它吗?
可以,只要您使用一个合适的(即具有真实域名的)测试环境。
### 我能以此运行自己的 SaaS 吗?
理论上可以,只要您遵守 [AGPL 许可证](./LICENSE),多租户功能已内置。实际上,以当前形式(自托管 Docker 容器)大规模扩展这将需要大量努力,并且维护起来会是一场噩梦。
如果我决定推出 SaaS,我将从头开始编写一个专有的 Kubernetes 编排器,并使用 SurrealDB 云端。
### 我想更改用户组。
只有超级用户可以执行此操作。作为非超级用户,您只能删除或转让您拥有的任何网站的所有权并删除您的账户。如果要启动新组,请注册(前提是注册功能已启用),否则请邀请用户。
### 这是一个 vibe coded 项目吗?
Hesperida 是一个 AI 辅助开发的项目。更具体地说;所有架构、模式和设计决策都是我自己的。第一批次要版本(大多数工具、数据库和编排器)的代码都是手工编写的。自 v0.3.0 起,约 90% 的代码是使用 OpenAI Codex 生成的。
### 您能添加/更改 X 功能吗?
请打开一个 [问题](https://github.com/rallisf1/hesperida/issues/new),我们会查看。
### 我如何贡献?
1. 创建一个问题
2. 叉仓库
3. 进行更改
4. 测试它们
5. 提交一个关闭您问题的拉取请求
## 许可证
AGPL v3
标签:accessibility, GNU通用公共许可证, HTTP 探测, MITM代理, nikto, Node.js, nuclei, Playwright, search engine optimization, SEO 扫描, SSL 证书检查, TIP, TypeScript, wapiti, wcag, Web 安全扫描, Whois 查询, 域名探测, 安全插件, 技术栈探测, 无障碍测试, 特征检测, 网站审计, 自动化攻击, 自托管, 请求拦截