Vartika-Mishra13/SentinelAI
GitHub: Vartika-Mishra13/SentinelAI
基于 MERN 栈构建的安全 API 网关,提供速率限制、威胁检测、异常评分和实时监控仪表板,保护 API 免受滥用和恶意攻击。
Stars: 0 | Forks: 0
# SentinelAI — AI 驱动的 API 网关与滥用检测系统
SentinelAI 是一个专注于安全的 API 网关,可实时监控流量、检测异常模式并自动封禁恶意客户端。它将滑动窗口速率限制、基于规则的异常评分、威胁检测和 Geo-IP 富化整合为一个单一的可部署系统,并配备了实时管理仪表板。
## 仪表板

*显示在一次模拟突发攻击后,实时威胁状态、总请求数、可疑活动和被封禁 IP 的统计面板。*

*实时流量 Feed 展示了状态的演变过程:正常 → 可疑 (3/5 → 4/5 → 5/5) → 已封禁,并附带了具体原因和时间戳。*
## 工作原理
每个传入的请求在到达任何路由之前,都会经过一个中间件链:
```
Request → threatDetection → apiKeyMiddleware / slidingRateLimiter → requestLogger → Route
```
**threatDetection** 使用正则表达式扫描 query params、request body 和 URL,以检测 SQL 注入、XSS 和路径遍历模式。如果匹配到任何模式,将立即返回 400 并予以拦截。
**apiKeyMiddleware** 负责验证 API key,检查该 IP 当前是否被封禁,通过 Redis 为每个用户应用固定窗口的每小时速率限制,并自动封禁超过突发阈值的 IP。
**slidingRateLimiter** 使用 Redis 有序集合来追踪可配置窗口内的请求时间戳。在请求达到阈值被完全封禁之前,接近阈值的请求会被标记为可疑状态 —— 从而在硬性切断之前为仪表板提供预警状态。
**requestLogger** 会在每次请求后运行,无论结果如何。它会对 IP 进行地理富化,计算异常分数(0–100),将日志写入 MongoDB,并在请求被拦截时通过 Nodemailer 发送电子邮件警报。
**anomalyScorer** 根据威胁类型(SQL 注入 +40,XSS +40)、请求状态(已封禁 +20,可疑 +10)、请求频率、发生时间(非工作时间 +10)以及未知地理来源(+10)来分配分数。分数上限为 100,并映射为“正常 / 可疑 / 严重”等级。
## 功能
- **双重速率限制** — 固定窗口(按用户每小时计算)和滑动窗口(可配置的窗口与限制),可通过模式标志进行切换
- **威胁检测** — 对每个请求进行 SQL 注入、XSS 和路径遍历扫描
- **异常评分** — 基于规则的 0–100 分数,并附带每个请求的可解释原因
- **自动 IP 封禁** — 超过突发阈值的 IP 将被封禁一段可配置的时长
- **Geo-IP 富化** — 使用 ip-api.com 并带有 geoip-lite 回退机制,配备 1 小时的内存缓存
- **电子邮件警报** — 每次请求被封禁时,通过 Nodemailer 发送 HTML 警报邮件
- **规则热配置** — 速率限制、突发阈值、封禁时长存储在 MongoDB 中,可直接在仪表板中修改而无需重新部署
- **管理仪表板** — 支持搜索、分页的实时流量 Feed、IP 封禁管理、API key 管理、请求压力趋势图以及智能警报面板
- **身份验证速率限制** — 登录和注册 endpoint 限制为每 15 分钟最多 10 次尝试
## 技术栈
| 层级 | 技术 |
|---|---|
| Frontend | React.js, Recharts, React Toastify |
| Backend | Node.js, Express.js |
| 数据库 | MongoDB Atlas (Mongoose) |
| 缓存 / 速率限制 | Upstash Redis |
| 身份验证 | JWT + bcryptjs |
| 电子邮件警报 | Nodemailer (Gmail) |
| Geo-IP | ip-api.com + geoip-lite |
## 项目结构
```
SentinelAI/
├── backend/
│ ├── config/
│ │ └── redis.js # Upstash Redis client
│ ├── controllers/
│ │ ├── adminController.js # Dashboard stats, IP/key management, rules
│ │ ├── authController.js # Signup, login
│ │ └── userController.js # API key generation, usage
│ ├── middleware/
│ │ ├── apiKeyMiddleware.js # Fixed window rate limiting + IP blocking
│ │ ├── authMiddleware.js # JWT verification
│ │ ├── rateLimiter.js # Mode switcher (fixed vs sliding)
│ │ ├── requestLogger.js # Logging, anomaly scoring, email alerts
│ │ ├── slidingRateLimiter.js # Sliding window rate limiting via Redis
│ │ └── threatDetection.js # SQLi, XSS, path traversal scanning
│ ├── models/
│ │ ├── BlockedIP.js
│ │ ├── RequestLog.js
│ │ ├── SecurityRule.js
│ │ ├── Usage.js
│ │ └── User.js
│ ├── routes/
│ │ ├── adminRoutes.js
│ │ ├── authRoutes.js # Rate limited (10 attempts / 15 min)
│ │ └── userRoutes.js
│ ├── utils/
│ │ ├── anomalyScorer.js # 0–100 scoring with explainable reasons
│ │ ├── emailAlert.js # HTML alert emails
│ │ ├── geoip.js # Geo enrichment with caching
│ │ └── securityRules.js # DB-driven rule fetching
│ └── server.js
├── frontend/
│ └── src/
│ ├── pages/
│ │ ├── Dashboard.js
│ │ ├── Login.js
│ │ └── Register.js
│ └── components/
│ └── RequestChart.js
├── loadtest.js # Load test script (burst + gradual phases)
└── README.md
```
## 本地运行
### 前置条件
- Node.js 18+
- MongoDB Atlas 账户(免费版即可)
- Upstash Redis 账户(免费版即可)
- 启用了应用密码的 Gmail 账户
### 1. 克隆仓库
```
git clone https://github.com/Vartika-Mishra13/SentinelAI.git
cd SentinelAI
```
### 2. 后端设置
```
cd backend
npm install
```
创建 `backend/.env`:
```
MONGO_URI=your_mongodb_connection_string
JWT_SECRET=your_jwt_secret
UPSTASH_REDIS_REST_URL=your_upstash_url
UPSTASH_REDIS_REST_TOKEN=your_upstash_token
ALERT_EMAIL=your_gmail@gmail.com
ALERT_EMAIL_PASSWORD=your_gmail_app_password
ADMIN_EMAIL=email_to_receive_alerts@gmail.com
PORT=5000
```
```
npm start
```
### 3. 前端设置
```
cd frontend
npm install
npm start
```
前端运行在 `http://localhost:3000`。注册一个账户,登录后仪表板即会自动加载。
## 测试速率限制
项目包含一个负载测试脚本,用于模拟两种真实的攻击模式:
```
# 从 root 目录
npm install axios
# 编辑 loadtest.js — 将 EMAIL 和 PASSWORD 设置为你的已注册账户
npm run loadtest
```
**阶段 1 — 突发攻击**:以 50ms 的延迟发送 20 个请求。滑动窗口(限制:5次/60秒)会在第 6 次请求时触发,并返回 429。你可以实时观察仪表板的数据变化。
**阶段 2 — 缓慢激增**:以 800ms 的延迟发送 15 个请求。展示了在完全封禁之前出现的可疑状态(逐渐逼近阈值)—— 这证明了滑动窗口不仅能捕获突发攻击,也能捕获缓慢攻击。
## 安全规则(热配置)
所有阈值均存储在 MongoDB 中,无需重启服务器即可直接在仪表板中进行修改:
| 规则 | 默认值 | 描述 |
|---|---|---|
| 滑动限制 | 5 | 每个滑动窗口的最大请求数 |
| 滑动窗口 | 60s | 滑动窗口持续时间 |
| 可疑阈值 | 60% | 触发“可疑”状态的限制百分比 |
| 突发次数 | 3 | 触发警报前突发窗口内的请求数 |
| 突发窗口 | 2s | 突发检测窗口 |
| IP 突发次数 | 10 | IP 被自动封禁前的请求数 |
| IP 封禁时长 | 60s | IP 保持封禁状态的时间 |
| 用户每小时限制 | 500 | 每个用户每小时的最大请求数 |
## 部署到 Render
### Backend
1. 将你的代码推送到 GitHub
2. 访问 [render.com](https://render.com) → New → Web Service
3. 连接你的代码仓库 → 选择 `backend` 文件夹作为根目录
4. Build command:`npm install`
5. Start command:`node server.js`
6. 在 Environment 标签下添加 `.env` 中的所有环境变量
7. Deploy
### Frontend
1. 访问 Render → New → Static Site
2. 连接你的代码仓库 → 选择 `frontend` 文件夹作为根目录
3. Build command:`npm install && npm run build`
4. Publish directory:`build`
5. 添加环境变量:`REACT_APP_API_URL=https://your-backend-url.onrender.com`
6. Deploy
## 作者
Vartika Mishra — [GitHub](https://github.com/Vartika-Mishra13)
标签:API网关, AppImage, CISA项目, DOE合作, MERN栈, MITM代理, Redis, Web应用防火墙, 异常检测, 搜索引擎查询, 流量监控, 自定义脚本, 配置错误