AdarshSingh1705/Intrusion-Detection-Gateway

GitHub: AdarshSingh1705/Intrusion-Detection-Gateway

基于 Node.js 的反向代理安全网关,通过并行防护层实时检测并拦截暴力破解、DoS 泛洪和注入攻击,保护后端服务免受常见 Web 威胁。

Stars: 0 | Forks: 0

# 入侵检测与防御网关 一个反向代理安全网关,位于任何 Web 应用程序的前端,并实时检查每个请求。它能够检测并拦截暴力破解、凭证填充、应用层 DoS 泛洪,以及 SQL 注入 / XSS payload —— 在它们触及源服务器之前。 ## 工作原理 每个传入的请求都会通过三个并行运行的独立防护层: ``` Client → Gateway (guards run in parallel) → Decision Engine → Allow / Throttle / Block / Challenge ↓ (on allow) Origin Server ``` | 防护层 | 检测内容 | 机制 | | ------------- | --------------------------------- | ------------------------------------------------ | | Auth Guard | 暴力破解、凭证填充 | 基于用户名 + IP 的 Redis 失败计数器 | | Rate Guard | 应用层 DoS / API 滥用 | 基于每个 IP 的固定窗口 Redis 计数器 | | Payload Guard | SQLi、XSS | 针对 body、query、cookies 的正则签名匹配 | 决策引擎使用固定的优先级顺序(注入 > 身份验证 > 速率 > 可疑 > 允许)合并这三个判定结果,并返回最终操作。 ## 服务 | Service | Port | Description | | ------------- | ----- | --------------------------------------------------------- | | `gateway` | 8080 | 反向代理 + 所有防护层 + 管理 API | | `demo-site` | 4000 | 故意未受保护的“受害者”应用 | | `redis` | 6379 | 快速状态 — 速率计数器、黑名单、token 吊销 | | `mongo` | 27017 | 持久状态 — 事件、警报、用户、租户 | | `dashboard` | 3000 | React 控制平面 — 实时日志、调查、设置 | ## 快速开始 **1. 克隆并配置** ``` git clone cd intrusion-detection-gateway cp .env.example .env ``` 编辑 `.env` 并至少设置: ``` JWT_SECRET=your_strong_secret_here ``` **2. 启动所有服务** ``` docker compose up --build ``` **3. 验证是否正在运行** ``` curl http://localhost:8080/ # → 来自 demo-site 的 HTML 登录页面(通过 gateway 代理) ``` **4. 打开控制台** 导航到 `http://localhost:3000` 并使用初始化的管理员凭据(默认:`admin` / `admin123`)登录。 ## 初始化 / 数据填充 首次启动时,网关会自动创建: | Resource | Value | | -------------- | ------------------------------------------------------- | | 管理员用户 | `ADMIN_USERNAME` / `ADMIN_PASSWORD`(来自 `.env`) | | 默认租户 | `tenantId: "default"` 及测试阈值 | 数据填充是幂等的 — 它会在创建前检查是否存在,因此每次重启时运行都是安全的。 要重置并使用不同的凭据重新进行数据填充: ``` docker compose down -v # wipe MongoDB volume # 在 .env 中编辑 ADMIN_USERNAME / ADMIN_PASSWORD docker compose up --build ``` ## 环境变量 | Variable | Required | Description | | ------------------------ | -------- | ------------------------------------------------------------------ | | `PORT` | 否 | 网关端口(默认`8080`) | | `MONGO_URI` | 是 | MongoDB 连接字符串 | | `REDIS_URL` | 是 | Redis 连接字符串 | | `JWT_SECRET` | 是 | 用于签署 access + refresh token 的密钥 | | `JWT_ACCESS_TTL` | 否 | Access token 有效期(默认`15m`) | | `JWT_REFRESH_TTL` | 否 | Refresh token 有效期(默认`7d`) | | `ADMIN_USERNAME` | 否 | 初始化的管理员用户名(默认`admin`) | | `ADMIN_PASSWORD` | 否 | 初始化的管理员密码(默认`admin123`) | | `DEMO_SITE_ORIGIN_URL` | 否 | 代理到的源地址(默认`http://demo-site:4000`) | | `BREVO_API_KEY` | 否 | Brevo API key — 启用邮件警报(管理员 + 用户通知) | | `ALERT_SENDER_EMAIL` | 否 | 所有警报邮件的发件人地址 | | `ADMIN_ALERT_EMAIL` | 否 | 管理员安全警报的收件人地址 | ## 邮件通知(Brevo) 当设置了 `BREVO_API_KEY` 时,网关会发送两类邮件: | Trigger | Recipient | Subject | | -------------------------------------------- | -------------------------------------- | ------------------------------------------------ | | 防护层触发(拦截/限流事件) | 管理员(`ADMIN_ALERT_EMAIL`) | `[Gateway Alert] ` | | 暴力破解后账户被锁定 | 受影响的用户(其注册的邮箱) | `Your account has been locked` | | 凭证填充 / 泛洪后 IP 被拦截 | 受影响的用户(其注册的邮箱) | `Suspicious activity detected on your account` | 这三者都是 **fire-and-forget** 的 — Brevo 的失败永远不会阻断响应路径。 如果未设置 `BREVO_API_KEY`,网关仍会正常运行。警报仍会写入 MongoDB 并在控制台中可见。不会发送任何邮件,也不会抛出任何错误。 要注册一个带有邮箱地址的用户以便接收通知: ``` curl -X POST http://localhost:8080/auth/signup \ -H "Content-Type: application/json" \ -d '{"username":"alice","password":"secret","email":"alice@example.com"}' ``` ## API 参考 ### 身份验证 — 公开端点 | Method | Path | Body | Response | | -------- | ----------------- | ---------------------------------- | ------------------------------------- | | `POST` | `/auth/signup` | `{ username, password, email? }` | `201 { userId }` | | `POST` | `/auth/login` | `{ username, password }` | `200 { accessToken, refreshToken }` | | `POST` | `/auth/refresh` | `{ refreshToken }` | `200 { accessToken }` | 登录响应: - `401` — 凭据无效 - `423` — 账户已锁定(达到暴力破解阈值) - `403` — 被防护层拦截(注入或凭证填充) ### 管理 API — 需要 `Authorization: Bearer ` | Method | Path | Description | | ---------- | --------------------------------------- | --------------------------------- | | `GET` | `/api/events?since=&severity=&limit=` | 可筛选的事件日志 | | `GET` | `/api/events/ip/:ip` | 特定 IP 的所有事件 | | `GET` | `/api/alerts?acknowledged=false` | 未确认的警报 | | `PATCH` | `/api/alerts/:id/acknowledge` | 将警报标记为已处理 | | `POST` | `/api/blocklist/:ip` | 手动拦截 IP(15 分钟 TTL) | | `DELETE` | `/api/blocklist/:ip` | 手动解封 IP | ### 租户接入 | Method | Path | Body | Response | | --------- | ------------------------------------- | ---------------------------------------------- | ---------------------------------------------- | | `POST` | `/api/tenants` | `{ domain, originUrl }` | `201 { tenantId, apiKey }` — key 仅显示一次 | | `GET` | `/api/tenants/:tenantId` | — | `200 { tenant config }` | | `PATCH` | `/api/tenants/:tenantId/thresholds` | `{ authFailMax, rateWarnMax, rateBlockMax }` | `200` | ## 测试防护层 ### Auth Guard — 暴力破解 首先注册一个用户,然后运行暴力破解模拟: ``` # 注册(email 是可选的,但启用 lockout 通知) curl -X POST http://localhost:8080/auth/signup \ -H "Content-Type: application/json" \ -d '{"username":"testuser","password":"correctpass","email":"testuser@example.com"}' # 运行 brute-force 模拟 cd attack-sim && node bruteforce.js ``` 预期:第 1–4 次尝试返回 `401`,第 5 次尝试返回 `423 account_locked`。 如果配置了 Brevo,`testuser@example.com` 会收到一封锁定通知邮件。 ### Rate Guard — 泛洪 ``` cd attack-sim && node flood.js ``` 预期:第 1–5 次请求返回 `200`,第 6–10 次返回 `429`(限流),第 11 次及以上返回 `403`(被拦截)。 ### Payload Guard — 注入 ``` cd attack-sim && node injection.js ``` 预期:所有 SQLi/XSS payload 返回 `403`,正常的请求返回 `401`(密码错误,未被拦截)。 ## 熔断器 网关每 10 秒监控一次源服务器。如果最近 5 次探测中有 ≥50% 失败,熔断器将开启,所有请求都会收到一个 `503` 维护页面,而不是处于挂起状态。经过 30 秒的冷却后,它将进入半开状态,并放行一个探测请求。如果成功,它将再次关闭。 测试方法:停止 demo-site 容器,观察网关在约 10 秒内切换到维护页面。 ``` docker compose stop demo-site ``` ## 控制台 位于 `http://localhost:3000` 的 React 控制台提供了三个视图: | Page | Description | | ----------- | --------------------------------------------------------------------------- | | Live Feed | 自动刷新的事件日志(5 秒轮询)、警报横幅、手动拦截按钮 | | Investigate | IP 查询 — 完整的事件历史记录、摘要统计、拦截 / 解封控制 | | Settings | 实时阈值滑块 — 更改通过管理 API 持久化到 MongoDB | 使用初始化的管理员凭据登录。控制台会将 `/api` 和 `/auth` 代理到网关,因此无需进行 CORS 配置。 ## 项目结构 ``` intrusion-detection-gateway/ ├── gateway/ │ ├── config/ │ │ ├── db.js # Mongoose connection │ │ ├── redis.js # ioredis client │ │ ├── signatures.js # SQLi / XSS regex patterns │ │ └── defaultTenant.js # Test thresholds (authFailMax:5, rateWarnMax:5, rateBlockMax:10) │ ├── guards/ │ │ ├── authGuard.js # Brute-force pre-check │ │ ├── rateGuard.js # Fixed-window flood detection │ │ └── payloadGuard.js # Signature matching │ ├── core/ │ │ ├── decisionEngine.js # Merges 3 verdicts → final action │ │ └── runGuards.js # Promise.all + logEvent + sendAlert │ ├── middleware/ │ │ ├── adminAuth.js # JWT verification for /api/* │ │ ├── circuitBreaker.js # 503 holding page when circuit open │ │ ├── guardCheck.js # Runs guards on /auth/* before route handler │ │ ├── logger.js # Fire-and-forget Event.create │ │ └── tenantScope.js # Sets req.tenantId = 'default' │ ├── models/ │ │ ├── Alert.js │ │ ├── Event.js │ │ ├── Tenant.js │ │ └── User.js # Includes optional email field │ ├── routes/ │ │ ├── auth.js # signup (email?), login, refresh │ │ ├── api.js # Management API (6 endpoints) │ │ └── tenants.js # Tenant CRUD + threshold patch │ ├── services/ │ │ ├── alerting.js # sendAlert (admin email) + notifyUser (user email) │ │ ├── healthMonitor.js # Circuit breaker state machine │ │ ├── lockout.js # Redis account lockout │ │ └── throttle.js # Redis IP blocklist │ ├── proxy.js # Fast-path blocklist check → runGuards → proxy │ ├── seed.js # Creates admin user + default tenant on first boot │ └── server.js # Entry point ├── dashboard/ │ ├── src/ │ │ ├── api/client.js # Fetch wrapper with auth header │ │ ├── pages/ │ │ │ ├── Login.jsx │ │ │ ├── LiveFeed.jsx │ │ │ ├── Investigate.jsx │ │ │ └── Settings.jsx │ │ └── App.jsx # Router + protected route guard │ └── vite.config.js # Proxies /api and /auth → gateway:8080 ├── demo-site/ │ └── server.js # Intentionally naive login form ├── attack-sim/ │ ├── bruteforce.js │ ├── flood.js │ └── injection.js ├── docker-compose.yml └── .env.example ``` ## 架构决策 - **Redis 错误时故障放行** — 如果 Redis 无法连接,防护层将跳过检查并记录一个降级事件,而不是拦截所有流量 - **fire-and-forget 日志记录** — 对 MongoDB 的事件写入和所有邮件发送永远不会阻断响应路径 - **固定窗口限流** — 允许在窗口边界处有高达 2 倍的突发流量;滑动窗口是记录在案的未来改进项 - **防护层并行运行** — `Promise.all` 确保检测延迟保持在最低水平,无论运行多少个防护层 - **Brevo 是完全可选的** — 警报始终会写入 MongoDB;邮件是一个附加层,仅在存在 `BREVO_API_KEY` 时激活 - **用户邮箱是可选的** — 注册接受 `email` 但不作要求;如果该字段不存在,通知将静默无操作
标签:API网关, AppImage, CISA项目, GNU通用公共许可证, MITM代理, Node.js, Redis, Web应用防火墙, 入侵防御, 反向代理, 搜索引擎查询, 版权保护, 红队行动, 自定义脚本, 请求拦截, 配置错误, 限流防刷