ph33nx/hono-honeypot

GitHub: ph33nx/hono-honeypot

Hono.js 轻量级安全中间件,通过 200+ 路径模式在路由前拦截漏洞扫描器与恶意探测,并支持 IP 记过封禁机制。

Stars: 4 | Forks: 0

hono-honeypot. Block bots before they reach your routes. Zero dependencies, MIT licensed.

# hono-honeypot [Hono.js](https://hono.dev) 的安全中间件。一个微型 WAF 和蜜罐路径拦截器,能够在漏洞扫描器(nuclei、nikto、sqlmap、dirbuster、gobuster、wpscan)、机器人爬虫以及暴力破解探测到达你的路由处理器之前将它们拦截。 基于在生产环境中对数十万个真实恶意请求的分析构建。模式匹配在所有 Hono 运行时(Cloudflare Workers、Bun、Deno、Node.js、Vercel Edge 和 Fastly Compute)中的运行时间均低于 1 毫秒。 ## 这是什么(以及不是什么) `hono-honeypot` 是 Hono.js 的**基于路径的攻击模式拦截器**。它会在已知扫描目标(`/wp-admin`、`/.env`、`/.git/`、`/actuator`、`/@fs/` 等)到达你的处理器之前拒绝这些请求,并可选择按 IP 封禁重复违规者。你可以将其视为一个微型 Web 应用防火墙(WAF)、扫描器偏转器或机器人拦截器。 | 拦截内容 | 不拦截的内容 | |---|---| | 漏洞扫描器:nuclei、nikto、sqlmap、dirbuster、gobuster、wpscan | 垃圾表单提交(请使用隐藏表单字段陷阱来处理) | | WordPress、PHP、cPanel、phpMyAdmin 探测 | 应用级别的速率限制(请使用单独的限流器) | | `.env`、`.git`、`.aws`、`.ssh` 窃取尝试 | DDoS 和流量型攻击(在 Cloudflare 或上游代理处终止) | | Vite 开发服务器漏洞 (CVE-2025-30208) | 针对 your own routes 的 OWASP Top 10 注入(输入验证应在处理器中进行) | | 路径遍历探测,SSRF 云元数据探测 | 行为式机器人检测(请使用指纹或设备智能服务) | | 涵盖 Spring Actuator、Magento REST、Exchange OWA、IoT 路由器、K8s 探测、CI/CD 管理面板等的 200 多种内置模式 | 身份验证或授权(此操作在你的 auth 中间件之前运行) | “honeypot”这个名字是比喻性的:当启用 IP 存储时,探测陷阱路径的扫描器会被困住(受到打击并被封禁)。它**不是**表单字段级的反垃圾邮件蜜罐。 ### OWASP 对齐 减少了 [**OWASP Top 10 2025 A02 Security Misconfiguration**](https://owasp.org/Top10/2025/)(原 A05:2021,在 2025 年版中排名第二)的攻击面。特别拒绝针对以下内容的侦察探测: - **生产环境中遗留的示例/旧版应用程序**,带有默认管理员帐户(OWASP A02 场景 #1:WordPress、phpMyAdmin、Adminer、Magento、cPanel) - **默认不安全的调试端点**(Spring `/actuator`、Django `/__debug__`、Laravel `/_ignition`、Vite `/@fs/`) - **在生产环境中启用了不必要的功能**(管理面板、开发工具路由、IoT 供应商后门) - **绝对不应该被 Web 访问到的敏感文件**(`.env`、`.git/`、`.aws/`、`.ssh/`、备份文件、依赖清单) 这是深度防御的一层,而不是配置审计器。请配合适当的加固、机密管理以及移除未使用的框架一起使用。 ## 安装 ``` npm install hono-honeypot ``` ## 快速开始 ``` import { Hono } from 'hono' import { honeypot } from 'hono-honeypot' const app = new Hono() app.use('*', honeypot()) ``` 就是这样。200 多种攻击模式即刻被拦截。以下所有选项均为**可选**。 ## API 参考 ### `honeypot(options?)` 返回 Hono 中间件。所有选项均为可选。 ``` app.use('*', honeypot({ patterns, // RegExp[] — additional patterns to block exclude, // RegExp[] — built-in patterns to remove status, // 410 | 404 | 403 — response status (default: 410) store, // HoneypotStore — enables IP strike/ban system strikeThreshold, // number — strikes before ban (default: 3) getIP, // (c: Context) => string — custom IP extraction onBlocked, // (info: BlockInfo) => void — custom block handler log, // boolean — console logging (default: true) })) ``` ## 功能特性 ### 模式匹配(无状态,零配置)

200+ attack patterns built in. wp-admin, .env, .git, /actuator, /@fs/. Smart anchoring, no false positives.

开箱即用,该中间件将请求路径与 200 多个正则表达式模式进行匹配,涵盖: | 类别 | 示例 | |----------|----------| | PHP/WordPress | `*.php`, `/wp-admin`, `/xmlrpc.php`, `/wp-content/` | | 管理面板 | `/admin`, `/phpmyadmin`, `/cpanel`, `/cgi-bin` | | CMS 框架 | `/typo3`, `/joomla`, `/drupal`, `/magento` | | Magento REST API | `/rest/V1/store/storeConfigs` 及存储范围变体 | | JS 框架指纹识别 | `/_next`, `/_rsc`, `/_vercel`, `next.config.js`, `nuxt.config.ts` | | 部署配置 | `serverless.yml`, `vercel.json`, `netlify.toml`, `package.json` | | Docker/容器 | `docker-compose.yml`, `Dockerfile`, `/docker/` | | AWS/云凭证 | `/aws/*`, `aws_s3`, `aws_ses`, `/.aws/` | | 版本控制 | `/.git/`, `/.svn/`, `/.hg/` | | 敏感文件 | `/.env`, `/.htaccess`, `/.htpasswd`, `*.sql` | | SSH/认证令牌 | `/.ssh/`, `/id_rsa`, `/.npmrc`, `/.pypirc` | | 系统路径遍历 | `/var/task/`, `/var/log/`, `/opt/` | | 命令注入 | `$(pwd)`、反引号注入 | | URL 规范化探测 | 零宽度 Unicode (`U+200B`、`U+FEFF` BOM、U+200C–U+200F、U+202A–U+202E 方向覆盖) | | 日志文件 | `*.log`, `error_log` | | Java/Spring Boot | `/WEB-INF`, `/manager/html`, `/solr`, `/actuator` | | 依赖清单 | `composer.json`, `Gemfile`, `requirements.txt` | | 所见即所得编辑器 (WYSIWYG) | `/ckeditor`, `/tinymce`, `/elfinder` | | 操作系统元数据 | `.DS_Store`, `Thumbs.db` | | 备份文件 | `*.bak`, `*.old`, `*.backup`, `*.swp` | | 路径遍历 / LFI | `../`, `..%2f`, `/etc/passwd`, `/proc/self/environ` | | Vite 开发服务器漏洞 | `/@fs/`, `/@vite/`, `/@id/` (CVE-2025-30208) | | Laravel/Django 调试 | `/_ignition`, `/__debug__` | | SSRF / 云元数据 | `/proxy/`, `169.254.169.254`, `/latest/meta-data` | | IoT / 路由器漏洞 | `/HNAP1/`, `/boaform/`, `/GponForm/`, `/setup.cgi` | | Microsoft Exchange/SharePoint | `/owa/`, `/aspnet_client/`, `/ecp/`, `/_layouts/`, `/_vti_bin/` | | 自托管应用 | `/nextcloud/`, `/owncloud/`, `/WebInterface/` (CrushFTP) | | 协作/监控 | `/geoserver/`, `/confluence/`, `/jira/`, `/grafana/`, `/kibana/`, `/prometheus/` | | CI/CD / DevOps | `/jenkins/`, `/portainer/`, `/gitea/`, `/gitlab/` | | 数据库管理别名 | `/adminer`, `/pma/`, `/myadmin/`, `/mysqladmin`, `/dbadmin` | | 网络邮件 | `/roundcube/`, `/webmail/` | | Kubernetes / 容器 | `/metrics`, `/healthz`, `/readyz`, `/livez`, `/.dockerenv` | | 暴力破解发现 | `/old`, `/test`, `/demo`, `/script`, `/2017`, `/2024` | 模式使用智能锚点来防止误报: ``` /admin → blocked (exact root match) /api/admin → allowed (nested path, not root) /login → allowed (legitimate app route) /blog → allowed (legitimate app route) ``` ### 自定义模式 添加特定于应用程序的模式。将与内置集合合并。 ``` app.use('*', honeypot({ patterns: [ /^\/internal-api/i, /^\/debug/i, ], })) ``` ### 排除内置模式 通过匹配正则表达式源字符串移除特定的内置模式。 ``` app.use('*', honeypot({ exclude: [ /^\/admin(\.php)?$/i, // Allow your own /admin route ], })) ``` ### 响应状态 默认为 `410 Gone`。可选:`404`、`403`。 ``` app.use('*', honeypot({ status: 404 })) ``` 为什么 `410 Gone` 是默认值: - Google 和 Bing 优先将 `410` 用于比 `404` 更快地取消索引 - 带有重试逻辑的扫描器将 `410` 视为永久性的,并且比遇到 `404` 时停止得更快 - 空的响应主体最大限度地减少了大容量探测下的带宽消耗 ## IP 记过/封禁系统

3 strikes, 24-hour ban. Memory, Redis, or Cloudflare KV. O(1) ban check before pattern matching.

如果没有存储,该中间件是无状态的:它拦截匹配的路径,但不会对重复违规者进行惩罚。有了存储,它会跟踪每个 IP 的记过情况,并封禁超过阈值的 IP。 **流程:** 1. 请求匹配攻击模式 → 记录针对该 IP 的记过 2. IP 达到 `strikeThreshold`(默认值:3)→ 该 IP 被封禁 3. 被封禁的 IP 发送任何请求 → 立即返回 `410` 响应,无需进行模式匹配(O(1) 查找) ### MemoryStore(内置) 基于 Map 且带有惰性 TTL 过期的进程内存储。适用于单进程部署和开发环境。 ``` import { honeypot, MemoryStore } from 'hono-honeypot' app.use('*', honeypot({ store: new MemoryStore({ strikeTTL: 3600, // optional — strike window in seconds (default: 3600 / 1 hour) banTTL: 86400, // optional — ban duration in seconds (default: 86400 / 24 hours) }), strikeThreshold: 3, // optional — default: 3 })) ``` ### 自定义存储 (Redis, KV 等) 实现 `HoneypotStore` 接口以使用任何存储后端。所有方法均可返回同步值或 Promises。 ``` interface HoneypotStore { /** Check if IP is banned. Called before pattern matching (fast path). */ isBanned(ip: string): Promise | boolean /** Record a strike. Return new total count. */ addStrike(ip: string): Promise | number /** Ban an IP. Called when strikes >= threshold. */ ban(ip: string): Promise | void /** Clear strikes. Called after ban is set. */ resetStrikes(ip: string): Promise | void } ``` #### Redis 示例 (ioredis) ``` import type { HoneypotStore } from 'hono-honeypot' import Redis from 'ioredis' const redis = new Redis() const redisStore: HoneypotStore = { async isBanned(ip) { return (await redis.exists(`honeypot:ban:${ip}`)) === 1 }, async addStrike(ip) { const key = `honeypot:strikes:${ip}` const count = await redis.incr(key) if (count === 1) await redis.expire(key, 3600) return count }, async ban(ip) { await redis.setex(`honeypot:ban:${ip}`, 86400, '1') }, async resetStrikes(ip) { await redis.del(`honeypot:strikes:${ip}`) }, } app.use('*', honeypot({ store: redisStore })) ``` #### Cloudflare KV 示例 ``` import type { HoneypotStore } from 'hono-honeypot' function createKVStore(kv: KVNamespace): HoneypotStore { return { async isBanned(ip) { return (await kv.get(`honeypot:ban:${ip}`)) !== null }, async addStrike(ip) { const key = `honeypot:strikes:${ip}` const current = parseInt((await kv.get(key)) || '0') const count = current + 1 await kv.put(key, String(count), { expirationTtl: 3600 }) return count }, async ban(ip) { await kv.put(`honeypot:ban:${ip}`, '1', { expirationTtl: 86400 }) }, async resetStrikes(ip) { await kv.delete(`honeypot:strikes:${ip}`) }, } } app.use('*', honeypot({ store: createKVStore(env.KV) })) ``` ## IP 提取 默认提取链:`cf-connecting-ip` > `x-forwarded-for`(第一个条目) > `x-real-ip` > `'unknown'`。 解析为 `'unknown'` 或空字符串的 IP 不会被记过系统跟踪(防止在无法确定 IP 时发生误封禁)。 使用自定义函数覆盖: ``` app.use('*', honeypot({ getIP: (c) => c.req.header('x-real-ip') || 'unknown', })) ``` ## 拦截处理器 (`onBlocked`) 在每次被拦截的请求上触发的自定义回调。提供此选项时,将抑制内置的控制台日志记录。 ``` app.use('*', honeypot({ onBlocked: (info) => { // info.ip — client IP // info.path — normalized request path // info.method — HTTP method // info.reason — 'pattern' | 'banned' // info.strikes — current strike count (when store is active, pattern matches only) // info.banned — true if this request triggered a new ban logger.warn(`honeypot: ${info.reason} ${info.ip} ${info.method} ${info.path}`) if (info.banned) { metrics.increment('honeypot.bans') } }, })) ``` 如果没有 `onBlocked`,当 `log: true`(默认值)时,中间件将记录到控制台: ``` 🍯 Blocked [203.0.113.5] GET /wp-admin 🚫 Banned [203.0.113.5] GET /.env BANNED ``` 设置 `log: false` 以抑制所有输出: ``` app.use('*', honeypot({ log: false })) ``` ## 导出 ``` import { honeypot, MemoryStore } from 'hono-honeypot' import type { HoneypotOptions, HoneypotStore, BlockInfo } from 'hono-honeypot' ``` | 导出 | 类型 | 描述 | |--------|------|-------------| | `honeypot` | 函数 | 中间件工厂 | | `MemoryStore` | 类 | 内置内存存储 | | `HoneypotOptions` | 接口 | 选项类型 | | `HoneypotStore` | 接口 | 存储适配器契约 | | `BlockInfo` | 接口 | 拦截事件负载 | ## 性能 | 指标 | 值 | |--------|-------| | 模式匹配开销 | 每个请求 <1ms | | 封禁检查 (存储) | O(1) 查找,在模式匹配之前运行 | | 内存占用 | ~10KB(模式数组) | | 包体积 | 除 `hono` peer dep 外零依赖 | ## 运行时兼容性 在所有 Hono.js 运行时上进行了测试:Cloudflare Workers、Bun、Deno、Node.js (>=18)、Vercel Edge Functions、Fastly Compute。 ## AI Agents 此软件包在已发布的 npm 包中附带了 `AGENTS.md`。支持 `AGENTS.md` 的 AI 编码代理(Claude Code、Cursor、GitHub Copilot、OpenAI Codex、Gemini CLI)将自动从 `node_modules/hono-honeypot/AGENTS.md` 中读取它。 ## 贡献 欢迎在 [github.com/ph33nx/hono-honeypot](https://github.com/ph33nx/hono-honeypot) 提交 Issue 和 PR。 ## 许可证 MIT
标签:AppImage, Bot防御, Bun, CISA项目, Deno, Fastly Compute, GNU通用公共许可证, Hono.js, IP封禁, MITM代理, Node.js, Serverless安全, SQL注入防御, SSRF防御, Vercel Edge, WAF, Web应用防火墙, 中间件, 安全防护, 实时处理, 密码管理, 恶意爬虫拦截, 暴力破解防御, 模式匹配, 流量清洗, 漏洞扫描器防御, 程序员工具, 网络安全, 自动化攻击, 自动化资产收集, 蜜罐, 证书利用, 误报拦截, 路径拦截, 路径遍历防御, 轻型WAF, 边缘计算, 隐私保护, 零依赖