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应用防火墙, 入侵防御, 反向代理, 搜索引擎查询, 版权保护, 红队行动, 自定义脚本, 请求拦截, 配置错误, 限流防刷