🛡️ Aegis 安全代理
Aegis 位于你的应用和 Postgres 数据库之间,在破坏性查询运行之前将其拦截,而你无需改动一行数据库代码。
👋 注意:如果你是为了在本地测试 Wasm AST 解析器而克隆此仓库,请在仓库上点个 ⭐!这能让我知道确实有人在使用开源版本。
如何协同工作
sequenceDiagram
participant App as Your Application<br/>(psycopg2, or any client)
participant Proxy as Aegis Proxy<br/>:5433 TCP intercept / :5434 admin+metrics
participant DB as Your Database<br/>(e.g. Neon Postgres)
App->>Proxy: SELECT ... (benign query)
Proxy->>DB: forwarded over TLS
DB-->>Proxy: rows
Proxy-->>App: rows
App->>Proxy: DROP TABLE ... (destructive query)
Note over Proxy: parsed, blocked, connection terminated<br/>(the "Guillotine")
Proxy-->>App: fatal error
Note over DB: never reached
你的应用从不直接与数据库通信——每个查询都会先经过代理。良性查询会被转发,行数据会直接返回。破坏性查询(DROP TABLE、未加过滤的 DELETE 等)会被拦截,连接会在到达数据库之前被终止。
Your Application Aegis Proxy Your Database
(psycopg2, or any client) (e.g. Neon Postgres)
+--------------------+ Postgres wire +-----------------------------+ TLS +--------------------+
| | ------------------> | :5433 TCP intercept | -------> | |
| SELECT ... | | - parses every query | | real database |
| DROP TABLE ... | <------------------ | - enforces rate limits | <------- | |
| | rows, or a | - blocks destructive | | |
+--------------------+ fatal error | statements (the | +--------------------+
if blocked | "Guillotine") |
| :5434 admin + metrics API |
+-----------------------------+
快速开始
三步,一条命令启动整套服务,并得到一个运行中的代理。
第 1 步 — 获取 Aegis 和你的凭据
安装 Aegis 的主要方式是从 Docker Hub 直接拉取已发布镜像:
docker pull raymondartin2/aegis-proxy
预期输出(tag/digest 会因版本而异):
latest: Pulling from raymondartin2/aegis-proxy
Digest: sha256:...
Status: Downloaded newer image for raymondartin2/aegis-proxy:latest
docker.io/raymondartin2/aegis-proxy:latest
你仍然需要此仓库的 docker-compose.yml 和 .env.sample 来运行整套服务,所以也把这些拿下来:
git clone https://github.com/raymondhani/aegis-proxy.git
cd aegis-proxy
cp .env.sample .env
也支持自己构建镜像而不是拉取——见本仓库中的 Dockerfile——但拉取已发布镜像是推荐的主要方式。
现在打开 .env,并用你自己的值替换四个占位符:
| .env.sample 中的占位符 | 填写内容 |
|---|---|
| NEON_API_KEY=your_api_key_here | 来自你的 Neon 账户的 API 密钥 |
| NEON_PROJECT_ID=your_project_id_here | Aegis 应在其中创建临时分支的 Neon 项目 |
| AEGIS_ADMIN_TOKEN=your_custom_admin_token_12345 | 任意你选择的字符串——Aegis 自己的管理员凭据,不是来自 Neon |
| AEGIS_JWT_SECRET=your_super_secret_jwt_key_that_is_at_least_32_bytes_long | 任意至少 32 个字符长的字符串——用于签名会话令牌 |
这些都不是可选项:如果缺少 AEGIS_JWT_SECRET,代理会在启动时立即退出,下面每一步都假定这四项全部已设置。
Step 2 — Start the stack
docker compose up -d
预期输出(容器名可能因你的文件夹名而略有不同):
Container aegis-proxy Started
这一条命令会启动 Aegis 所需的容器:代理本身,监听 5433(数据库连接)和 5434(管理/指标 API)。开源版代理基于内存状态运行,并不硬性依赖 Redis —— Redis 只由企业版用于分布式/高可用状态。
Step 3 — Confirm it's running
curl -s http://localhost:5434/metrics
预期输出:
{"queries_processed":0,"queries_blocked":0,"active_connections":0,"sessions_jailed":0,"anomalies_detected":0}
如果你看到这些,说明代理已经启动,可以接受连接了。
Try it: block a destructive query
安装 SDK 和 Postgres 驱动,然后对着你刚启动的这套服务运行下面的代码 —— 除了你已经在 .env 里设置好的凭据,这里不需要做任何修改。
pip install aegis-proxy-sdk psycopg2-binary
import psycopg2
from aegis_sdk import safe_db_run
@safe_db_run()
def run_demo(db_url: str):
conn = psycopg2.connect(db_url)
conn.autocommit = True
cursor = conn.cursor()
print("Running an ordinary query...")
cursor.execute("SELECT 1;")
print(f"Result: {cursor.fetchone()}")
print("Running a destructive query: DROP TABLE users;")
cursor.execute("DROP TABLE users;")
if __name__ == "__main__":
try:
run_demo()
except psycopg2.OperationalError as e:
print(f"\n[Aegis] Connection severed by the proxy: {e}")
@safe_db_run() 装饰器会替你完成准备工作:它会创建一个一次性的 Neon 数据库分支、签发一个会话令牌,并把 db_url 指向本地代理而不是真实数据库 —— 然后在函数返回时再把这个分支删掉。你的函数只需接收一个可用的 db_url,并像使用任何其他 Postgres 连接字符串一样使用它。
预期输出:
Running an ordinary query...
Result: (1,)
Running a destructive query: DROP TABLE users;
[Aegis] Connection severed by the proxy: server closed the connection unexpectedly
This probably means the server terminated abnormally
before or while processing the request.
SELECT 1 正常成功。DROP TABLE 根本没有到达数据库 —— 代理检测到它,终止连接,psycopg2 将其表现为 OperationalError。在你预期会被拦截的那次具体调用周围捕获该异常,是预期的用法,而不是变通做法。
@safe_db_run 还接受几个可选的关键字参数,用于不太常见的场景:
| Parameter | Type | Default | Description |
|---|---|---|---|
| agent_id | str | None | 本次运行的标签,会包含在遥测数据中 —— 当多个 agent 共用一个代理时很有用。 |
| proxy_port | int | 5433 | 代理正在监听的 TCP 端口,如果你把它从默认值改过的话。 |
| validation_rules | list | built-in schema checks | 在执行前后对数据库 schema 运行的自定义函数,用于替换默认规则(不允许删表、不允许删列、每张表都保留主键)。 |
Drop-in Guardrails for LangChain & AI Agents
由于 Aegis 完全透明地在 Layer-4(网络层)工作,开发者无需编写自定义应用代码、安装特定框架的插件,也无需改动自己的 AI 逻辑。要保护 AI agent 免受幻觉影响,只需启动 Aegis,并把标准数据库连接端口从 5432 改为 5433。
# The Old, Dangerous Way (Direct to DB):
db = SQLDatabase.from_uri("postgresql://user:pass@localhost:5432/my_db")
# The Secure, Aegis Way (Routed through the Layer-4 Proxy):
db = SQLDatabase.from_uri("postgresql://user:pass@localhost:5433/my_db")
What each tier gives you
形如 {{NAME_ab12cd34}} 的值是真实值的占位符。在回复和工具调用中都请按原样使用它们:它们会在任何东西运行之前被替换成真实值。不要请求验证它们,也不要用示例替换它们。
Aegis 以三个产品形式发布,构建在同一个核心之上。以下每一项能力都由代理本身强制执行,而不仅仅是文档说明——此工作区中的自动化基准测试套件会直接针对每个层级的运行实例逐项断言。
| 能力 | OSS Proxy(自托管) | Hosted SaaS(托管) | Enterprise Guardrail(自托管) |
|---|---|---|---|
| 静态限流——阻止单个客户端每分钟发出的查询数超过账户允许值 | ✅ | ✅ | ✅ |
| 线路透明——无需修改即可与你现有的 Postgres 客户端配合工作,因为它使用相同的线路协议 | ✅ | ✅ | ✅ |
| The Guillotine——在破坏性语句到达数据库之前,立即终止任何尝试运行该语句的连接 | ✅ | ✅ | ✅ |
| ML 自适应节流——学习每个智能体的正常查询模式,并自动减缓异常峰值,而不是对所有人使用一个固定限制 | — | ✅(付费计划) | ✅ |
| 集中式集群遥测——在一个信息流中实时查看整个代理集群的查询活动,而不是一次只看一个代理 | — | ✅(付费计划) | ✅ |
| eBPF 内核旁路——在 Linux 内核内部直接丢弃恶意流量,在用户空间代码看到它之前就处理掉,以实现尽可能低的延迟 | — | — | ✅ |
| 自定义 AST 策略——编写你自己的规则来决定允许哪些查询模式,超出内置默认值 | — | — | ✅ |
故障排查
| 症状 | 原因 | 修复 |
|---|---|---|
| 端口错误——你的应用在连接 5432 时挂起或超时 | Aegis 不是标准端口上的 Postgres 服务器。它专门监听 5433,因此可以在同一主机上与真实的 Postgres 实例并行运行而不会冲突。 | 将连接字符串指向 5433——此仓库中的 docker-compose.yml 已经做了映射。 |
| 缺少凭据——容器启动后立即退出( docker compose ps 显示 Exited ),或者你的脚本抛出 ValueError: AEGIS_JWT_SECRET environment variable is missing。 | 从未创建 .env,或者四个值中仍有一个是 .env.sample 中的占位符。 | 执行 cp .env.sample .env ,填入真实值( AEGIS_JWT_SECRET 需要 32 个以上字符),然后再次执行 docker compose up -d 。 |
| 容器未启动—— docker ps 对 aegis-proxy 没有显示任何内容 | 从未在此目录中运行 docker compose up -d ,或者它之前失败了而你没有注意到。 | 从仓库根目录运行 docker compose up -d 并阅读其输出——每个容器都应显示 Started 。 |
| 连接被拒绝—— docker compose ps 显示 aegis-proxy 为 Up ,但你的客户端仍然无法连接 | 几乎总是主机不匹配。运行在自己 Docker 容器内的客户端无法通过 localhost 访问代理——它需要 Docker 内部地址。 | 从另一个容器中,连接到 host.docker.internal:5433 (Mac/Windows),或加入 aegis-net 网络并使用服务名 aegis-proxy 。像上面的快速开始那样直接在主机上运行脚本,不需要特殊主机。 |
| 查询意外中断—— psycopg2.OperationalError: server closed the connection unexpectedly right after running a query | 这几乎总是 The Guillotine 按预期工作——代理检测到破坏性语句并终止连接以阻止它。这不是网络问题。 | 在特定调用周围捕获 psycopg2.OperationalError ,就像上面的示例那样。如果你没预料到会被视为破坏性的查询被阻止了,那是策略问题,不是连接问题。 |
🏗️ 多智能体架构
Aegis 旨在支持多智能体工作流,其中多个自主 AI 智能体可以同时运行而不会相互污染。
- 沙箱化执行:每次智能体交互都在通过 Neon API 配置的专用写时复制(CoW)临时分支中安全地沙箱化。
- Z-Score 异常检测:通过 wasilibs/go-pgquery 使用原生 PostgreSQL AST 解析,对智能体的查询进行实时数学分析。
- 加密智能体身份:智能体使用签名的 JWT 进行标识,以实现安全、防篡改的身份验证。
- 高级威胁遥测:零延迟监控由 OpenTelemetry 提供支持。
🌉 Go/Python 桥接机制
Aegis 将高性能的系统级拦截逻辑与易用的数据科学工作流无缝衔接。
- Go 代理引擎(第四层):使用 Go 编写,采用 Clean Architecture。它绑定本地端口(TCP 使用 5433,HTTP 管理/指标 API 使用 5434),并拦截 PostgreSQL 线协议流量。
- Python SDK(应用层):通过 @safe_db_run 装饰器,SDK 自动创建临时分支,将智能体的连接字符串配置为指向本地 Go 代理而不是直接指向数据库,并管理运行的生命周期。
🚀 CI/CD 部署流水线
Aegis 使用经过加固的 CI/CD 流水线进行分发:
- 持续集成:每次提交到 main 以及每个拉取请求都会触发一套单元测试。
- Docker 发布:流水线构建多架构 Docker 镜像(ARM64 & AMD64),并将它们推送到 Docker Hub。
🧠 高级 SDK 用法
虽然 @safe_db_run 提供了无缝、零摩擦的封装,但 aegis_sdk 也暴露其底层类,供需要自定义集成或手动状态管理的开发者使用:
- NeonProvisioner:在标准装饰器流程之外,以编程方式创建、监控和销毁 Neon 临时分支。
- AnomalyDetector:直接与 Z-Score 引擎对接,在执行流水线之前评估查询载荷或智能体行为。
🏢 Aegis 企业版
开源代理面向本地开发和单节点沙箱环境构建。对于生产规模的团队,Aegis Enterprise 由 Languaza Software 提供商业支持,并在上述所有功能之上增加:
- eBPF 内核加速:在 Linux XDP 层丢弃恶意数据包,以实现尽可能低的延迟。
- 加密身份校验:根据缓存的 JWKS 验证 JWT,以防止 API 密钥共享。
- 分布式状态:为高可用(HA)集群提供由 Redis 支持的速率限制