ThinkWatchProject/ThinkWatch
GitHub: ThinkWatchProject/ThinkWatch
企业级 AI 安全网关,统一认证、路由、计费与审计,解决 AI 工具使用中的可见性、合规与成本失控问题。
Stars: 221 | Forks: 4
# ThinkWatch
**[English](README.md) | [中文](README.zh-CN.md)**
**企业级安全网关,专为 AI 而设计。** 统一认证、审计并管控组织内所有 AI API 调用与 MCP 工具调用——通过单一控制平面实现。
就像 SSH 网关是所有服务器访问的统一入口,ThinkWatch 是所有 AI 访问的统一入口。每个模型请求、每次工具调用、每一枚 Token,都经过认证、授权、速率限制、日志记录与计费。
```
┌──────────────────────────────────────┐
Claude Code ──────>│ │──> OpenAI
Cursor ───────────>│ Gateway :3000 │──> Anthropic
Custom Agent ─────>│ AI API + MCP Unified Proxy │──> Google Gemini
CI/CD Pipeline ───>│ │──> Azure OpenAI / AWS Bedrock
└──────────────────────────────────────┘
┌──────────────────────────────────────┐
Admin Browser ────>│ Console :3001 │
│ Management UI + Admin API │
└──────────────────────────────────────┘
```
## 为什么要使用 ThinkWatch?
随着 AI 代理在工程团队中广泛使用,组织面临日益严峻的治理挑战:
- **API 密钥散落各处** — 硬编码在 `.env` 文件、共享在 Slack、从未轮换
- **零可见性** — 谁用了哪个模型、用了多少 Token、产生了什么成本?
- **无访问控制** — 每个开发者都能直接访问所有模型与所有 MCP 工具
- **合规缺口** — AI 辅助代码生成或数据访问缺乏审计追踪
- **成本意外** — 每月无法解释或归因的 AI 账单
通过一次部署,ThinkWatch 即可解决所有问题。
## 核心功能
### AI API 网关
- **多格式 API 代理** — 在单个端口原生支持 OpenAI Chat Completions(`/v1/chat/completions`)、Anthropic Messages(`/v1/messages`)与 OpenAI Responses(`/v1/responses`)API;可作为 Cursor、Continue、Cline、Claude Code 以及 OpenAI/Anthropic SDK 的直接替代
- **多提供商路由** — OpenAI、Anthropic、Google Gemini、Azure OpenAI、AWS Bedrock 或任意 OpenAI 兼容端点
- **自动格式转换** — Anthropic Messages API、Google Gemini、Azure OpenAI、AWS Bedrock Converse API 等,统一接口背后完成转换
- **提供商自动加载** — 启动时从数据库加载活跃提供商并注册到模型路由器;默认模型前缀(`gpt-`/`o1-`/`o3-`/`o4-` 对应 OpenAI,`claude-` 对应 Anthropic,`gemini-` 对应 Google)自动路由;Azure 与 Bedrock 需要显式注册模型
- **流式 SSE 透传** — 零开销转发,配合实时 Token 计数
- **虚拟 API 密钥** — 可签发作用域化的 `tw-` 密钥;同一 `tw-` 令牌可在 AI 网关与 MCP 网关通用,通过 per-key `surfaces` allowlist 控制
- **API 密钥生命周期管理** — 支持自动轮换、宽限期、每密钥不活跃超时、过期警告与后台策略强制
- **可组合速率限制与预算** — 多窗口滑动限制(1m / 5m / 1h / 5h / 1d / 1w)与自然周期令牌预算(日/周/月),按用户、API 密钥、提供商或 MCP 服务器区分。详见下文 [速率限制与预算](#速率限制与预算)
- **每模型 Token 加权** — 可通过 `input_multiplier` / `output_multiplier` 配置,使 gpt-4o 的 Token 计数高于 gpt-3.5
- **电路断路器** — 三态(闭合/打开/半开)断路器,支持可配置失败阈值与恢复周期
- **带指数退避的重试** — 针对网络错误与上游速率限制的可配置重试与抖动
- **实时成本追踪** — 支持按模型定价与团队归属
### MCP 网关
- **集中式工具代理** — 单个 MCP 端点聚合所有上游服务器的工具
- **命名空间隔离** — `github__create_issue`、`postgres__query`,避免工具命名冲突
- **工具级 RBAC** — 精确控制哪些用户或角色可以调用哪些工具
- **连接池与运行状况监控** — 自动重连与后台运行状况检查
- **完整审计追踪** — 每次工具调用均记录用户、参数与响应
### 安全与合规
- **双端口架构** — 网关(公网面向)与控制台(内网专用)分离端口
- **基于角色的访问控制** — 5 级 RBAC:超级管理员、管理员、团队负责人、开发人员、访客
- **SSO/OIDC** — 可对接 Zitadel、Okta、Azure AD 或任意 OIDC 兼容提供者
- **AES-256-GCM 加密** — 提供商 API 密钥与密钥在静态时加密
- **SHA-256 密钥哈希** — 虚拟 API 密钥以哈希存储,明文仅展示一次
- **内容安全策略** — 控制台端口启用 CSP 标头,防止 XSS 与注入攻击
- **JENT 熵强制** — 最小 32 字符密钥并在启动时验证熵值
- **启动依赖验证** — 在接受流量前验证 PostgreSQL、Redis 与加密密钥的可用性并提供明确错误信息
- **安全标头** — X-Content-Type-Options、X-Frame-Options、CORS 白名单、请求超时
- **软删除** — 用户、提供商与 API 密钥使用软删除(`deleted_at` 列),30 天后自动清理
- **密码复杂度** — 最小 8 位,含大小写字母与数字
- **会话 IP 绑定** — 管理员会话绑定客户端 IP,盗取令牌无法跨网络重放
- **Distroless 容器** — 生产环境最小攻击面(2MB 运行时镜像,无 Shell)
### 运维与配置
- **动态配置** — 大多数设置保存在数据库(`system_settings` 表),可通过 Web UI(管理员 > 设置,7 个分类标签页)配置
- **首次运行向导** — 引导式 `/setup` 向导创建超级管理员账户、配置站点,并可选地添加首个提供商与 API 密钥
- **配置指南** — 内置 `/gateway/guide` 页面,提供 Claude Code、Cursor、Continue、Cline、OpenAI SDK、Anthropic SDK 与 cURL 的复制粘贴式设置说明,自动探测网关 URL
- **多实例同步** — 配置变更通过 Redis Pub/Sub 在各实例间传播
- **数据保留策略** — 可配置使用记录与审计日志的保留周期,并自动每日清理
### 可观测性
- **Prometheus 指标** — 网关端口(3000)提供 `gateway_requests_total`、`gateway_request_duration_seconds`、`gateway_tokens_total`、`gateway_rate_limited_total`、`circuit_breaker_state`、`gateway_stream_completion_total`、`audit_log_dropped_total` 等。**默认禁用** — 设置 `METRICS_BEARER_TOKEN`(密钥生成脚本会自动填充)即可挂载该路由;未设置时返回 404 且不安装 Prometheus 记录器(零内存/CPU 开销)
- **增强型健康检查** — `/health/live`(存活探针)、`/health/ready`(就绪探针,验证 PostgreSQL、Redis **及至少一个活跃提供商** — 防止 K8s 将 AI 流量路由到路由器为空的全新 Pod)、`/api/health`(延迟与连接池统计详情)
- **ClickHouse 驱动的审计日志** — 基于 ClickHouse(列式 OLAP 数据库)的跨 API 调用与工具调用 SQL 可查询审计日志
- **审计日志转发** — 多通道投递:UDP/TCP Syslog(RFC 5424)、Kafka 与 HTTP Webhook,可将审计事件路由至任意 SIEM、数据湖或告警管道
- **用量分析** — 按用户、团队、模型与时间段统计 Token 消耗
- **成本分析** — MTD 支出、预算利用率、每模型成本明细
- **健康仪表盘** — PostgreSQL、Redis、ClickHouse 与所有 MCP 服务器的实时状态
- **统一日志探索器** — 从单一页面跨审计、网关、MCP、访问与平台日志进行搜索,支持结构化查询语法
## 速率限制与预算
ThinkWatch 在每个网关请求上并行执行两种配额限制,
两者均通过同一管理 UI 管理:
| | 滑动窗口速率限制 | 自然周期预算上限 |
|---|---|---|
| **计数对象** | 请求数 或 加权 Token,取决于规则的 `metric` | 仅加权 Token |
| **窗口形状** | 滚动 60 格:`1m / 5m / 1h / 5h / 1d / 1w` | 日历对齐:`daily / weekly / monthly`(周期边界) |
| **后端存储** | Redis ZSET 风格桶 | Redis INCR 计数器,键为 `subject:period:bucket_id` |
| **触发时机** | 预检(请求计数)与后检(Token 计数) | 仅后检 |
| **严格/宽松** | 请求计数为硬限制,Token 计数为软限制 | 软上限 —— 单个请求可能超过限制,随后同一周期内后续请求将被拒绝 |
### 主体
单个请求可同时受多条规则与多个预算约束。引擎将请求解析为 `(subject_kind, subject_id)` 集合,并对所有启用规则在原子 Lua 校验中统一执行。
**任一规则拒绝 → 请求被拒绝。全部或 nothing INCR。**
| 主体 | 速率限制规则 | 预算上限 |
|---|---|---|
| `user` | ✅ ai_gateway / mcp_gateway | ✅ |
| `api_key` | ✅ ai_gateway / mcp_gateway | ✅ |
| `provider` | ✅ ai_gateway 仅 | ✅ |
| `mcp_server` | ✅ mcp_gateway 仅 | ❌(无 Token 成本概念) |
| `team` | (使用 user / api_key) | ✅ |
对 AI 请求,引擎解析为:`api_key + user + provider`。对 MCP 请求:`user + mcp_server`。各主体限制叠加 —— 开发者可拥有个人上限、其 API 密钥可设更紧上限、提供商也可设全局上限,三者同时生效。
### 三种“Token”含义
系统中有三个数值,请勿混淆:
| 数值 | 来源 | 用途 | 显示位置 |
|---|---|---|---|
| **原始 Token** | `usage_records.input_tokens / output_tokens` | 实际提供商计费 Token 数 | 分析与成本报告 |
| **加权 Token** | `raw × models.input_multiplier / output_multiplier` | 配额统计(速率限制与预算) | 限制面板“X / Y 已用” |
| **USD 成本** | `raw × models.input_price / output_price` | 计费 | 成本页面 |
`models` 的两列相互独立。加权 Token 为*相对*单位(约定 gpt-3.5-turbo = 1.0),无全局美元价值。USD 始终来自真实每 Token 价格。默认所有模型乘数为 `1.0`,即配额按原始 Token 计数;可在模型管理页面调整乘数,使 100 万 Token 月度配额能承受单次 gpt-4o 突发。
### 示例
```
On the developer USER subject:
rate_limit_rule ai_gateway / requests / 60s → 60
rate_limit_rule ai_gateway / tokens / 1d → 1_000_000
budget_cap monthly → 20_000_000
On the OpenAI PROVIDER subject:
rate_limit_rule ai_gateway / requests / 1h → 100_000
```
来自任意开发者密钥对 gpt-4o 的请求需通过以下检查:
1. 开发者的每分钟请求规则
2. OpenAI 提供商的每小时请求规则
3. 响应后的开发者每日 Token 规则
4. 响应后的开发者月度 Token 预算
任一失败即返回 429,并在响应体中标注规则标签(如 `user:requests/1m`、`provider:requests/1h` 等)。
### 失效模式
当 Redis 不可用时,引擎默认**开启**并递增
`gateway_rate_limiter_fail_open_total` / `gateway_budget_fail_open_total`
指标,使 AI 控制平面在 Redis 短暂抖动期间仍可运行。
若操作者更倾向于拒绝流量而非漏记,可开启 `security.rate_limit_fail_closed = true`;此时引擎对无法校验的请求返回 429(`rate_limiter_unavailable`)并递增 `gateway_rate_limiter_fail_closed_total`。
### 预算告警
超过任意预算阈值的 50% / 80% / 95% / 100% 会触发结构化
`budget threshold crossed` 警告日志并递增
`gateway_budget_alert_total{subject_kind, period, threshold_pct}`。
每个阈值在每个周期桶内最多触发一次 —— 若单次请求直接从 60% 跨越至 100%,则 80 / 95 / 100 三条线会在该响应中全部触发,但同一周期内的后续请求不会重复触发。
### 流式 Token 统计
Token 限制规则与预算上限同样适用于流式响应,
前提是上游在 SSE 流中透出用量:
- **OpenAI**:需在请求体中设置 `stream_options.include_usage = true`
- **Anthropic**:自动捕获最终 `message_delta` 事件的累计用量
若上游未在流中透出用量,后检会计数将静默 no-op —— 速率限制与预算计数器仍基于上游提供的数据保持准确。
### PII 脱敏与流式响应
PII 脱敏器(在管理员 > 设置 > PII 模式中配置)会在每个提示转发上游前运行 —— 邮箱、电话、身份证等替换为 `{{EMAIL_xxx_1}}` 格式占位符,使上游无法看到原始数据。
在**非流式**响应中,网关会在返回前执行 `restore_response`,让客户端看到模型原本会回显的原始 PII。
在**流式**(SSE)响应中,网关**不**还原占位符 —— 跨分块重组属于独立项目。因此流式客户端若模型回显用户 PII,会看到占位符原文。提示侧脱敏仍生效,上游提供方无论如何都不会看到原始 PII;仅在流式场景下这是客户端层面的外观差异。如需原始文本恢复,请将客户端切换为非流式模式。
## 技术栈
| 层级 | 技术 |
|------|------|
| 后端 | Rust、Axum 0.8、SQLx 0.8、fred 10(Redis)、OpenTelemetry |
| 前端 | React 19、TypeScript 6、Vite 8、shadcn/ui、Tailwind CSS 4 |
| 数据库 | PostgreSQL 18 |
| 缓存与速率限制 | Redis 8 |
| 审计日志存储 | ClickHouse(列式 OLAP 数据库) |
| SSO | Zitadel(或其他任意 OIDC 提供者) |
| 容器 | Distroless(2MB 运行时),K8s 的 Helm Chart |
## 快速开始
```
# 1. 启动基础设施
make infra
# 2. 启动后端(网关 :3000 + 控制台 :3001)
cp .env.example .env
make dev-backend
# 3. 启动前端开发服务器
cd web && pnpm install && pnpm dev
# 4. 在 http://localhost:5173/setup 完成设置向导
```
请参考 **[部署指南](https://thinkwat.ch/docs/deployment-guide)** 获取 Docker Compose 或 Kubernetes 生产环境部署说明。
## 文档
完整文档:**[thinkwat.ch/docs](https://thinkwat.ch/docs)**
| 文档 | 说明 |
|------|------|
| **[架构](https://thinkwat.ch/docs/architecture)** | 系统设计、双端口模型、数据流图 |
| **[部署指南](https://thinkwat.ch/docs/deployment-guide)** | Docker Compose、Kubernetes Helm、SSL、生产加固 |
| **[配置](https://thinkwat.ch/docs/configuration)** | 所有环境变量及其影响 |
| **[API 参考](https://thinkwat.ch/docs/api-reference)** | 网关与控制台的完整端点文档 |
| **[安全](https://thinkwat.ch/docs/security)** | 认证模型、加密、RBAC、威胁模型、加固清单 |
| **[密钥轮换](https://thinkwat.ch/docs/secret-rotation)** | 提供商密钥、JWT 密钥与管理员凭证轮换 |
## 端口架构
| 端口 | 服务 | 暴露范围 | 用途 |
|------|------|----------|------|
| `3000` | 网关 | **公网** — 暴露给 AI 客户端 | `/v1/chat/completions`、`/v1/messages`、`/v1/responses`、`/v1/models`、`/mcp`、`/metrics`†、`/health/*` |
| `3001` | 控制台 | **内网** — 需通过 VPN/防火墙 | `/api/*` 管理端点、Web UI |
† 仅当设置 `METRICS_BEARER_TOKEN` 时挂载 `/metrics`;未设置时返回 404 且不安装 Prometheus 记录器(零内存/CPU 开销)。
## 项目结构
```
ThinkWatch/
├── crates/
│ ├── server/ # Dual-port Axum server (gateway + console)
│ ├── gateway/ # AI API proxy: routing, streaming, rate limiting, cost tracking
│ ├── mcp-gateway/ # MCP proxy: JSON-RPC, tool aggregation, access control
│ ├── auth/ # JWT, OIDC, API key, password hashing, RBAC
│ └── common/ # Config, DB, models, crypto, validation, audit logger
├── migrations/ # 12 PostgreSQL migration files
├── web/ # React frontend — ~20 page components
├── deploy/
│ ├── docker/ # Dockerfile.server (distroless), Dockerfile.web (nginx)
│ ├── docker-compose.yml # Production deployment
│ ├── docker-compose.dev.yml # Development (PG + Redis + ClickHouse + Zitadel)
│ └── helm/think-watch/ # Kubernetes Helm chart
└── ...
```
## 许可证
ThinkWatch 在 **[商业源码许可证 1.1](LICENSE)** 下提供源码可用。
非生产使用免费。生产使用免费上限为每月 **10,000,000** 计费 Token 与 **10,000** 次 MCP 工具,超出阈值需商业许可并按使用层级定价。
详见 [LICENSING.md](LICENSING.md) 获取生产使用阈值、计费 Token 与 MCP 工具调用定义、层级模型及迁移至 `GPL-2.0-or-later` 的说明。
## 星标历史
标签:AI API 代理, AI API管理, AI安全, AI审计, AI成本管理, AI治理, Anthropic, AWS Bedrock, Azure OpenAI, Chat Copilot, CIS基准, Docker, Gemini, MCP代理, OpenAI, PostgreSQL, RBAC, React, Redis, Rust, Syscalls, Token追踪, 企业AI, 企业级AI网关, 内存规避, 反向代理, 可视化界面, 多模型支持, 大语言模型蜜罐, 子域名突变, 安全网关, 安全防御评估, 审计日志, 成本追踪, 搜索引擎查询, 测试用例, 统一代理, 网络流量审计, 自托管LLM, 认证授权, 请求拦截, 通知系统