mohameduk/Ubag_protocol

GitHub: mohameduk/Ubag_protocol

UBAG 是一个在 Web 边缘为自主 AI Agent 提供加密身份认证与请求路由的开放参考实现,让站点能自动区分人类和 Agent 并直接提供结构化数据。

Stars: 0 | Forks: 0

# UBAG Web 层 ### 通用行为授权网关 — Web 层 [![CI](https://github.com/mohameduk/Ubag_protocol/actions/workflows/ci.yml/badge.svg)](https://github.com/mohameduk/Ubag_protocol/actions/workflows/ci.yml) [![License: MIT](https://img.shields.io/badge/License-MIT-blue.svg)](LICENSE) [![status: experimental](https://img.shields.io/badge/status-experimental-orange.svg)](#项目状态) **Web 边缘的 Agent 身份与路由。开放参考实现。** 当自主 Agent 访问网站时,UBAG 会验证*它是谁*并进行相应的路由: 人类路由至普通站点,已认证的 Agent 路由至纯净的 JSON-LD,未知的 bot 路由至加密挑战。MCP 标准化了 Agent 与工具的通信方式 — 但它在 Web 层留下了一个空白:在没有人类参与的情况下如何确认 Agent 身份。这就是填补这一空白的层。 ## 问题所在 当自主 MCP Agent 如今访问网站时: - 网站无法验证*它是谁* - 它像 2005 年的任何 bot 一样抓取原始 HTML - 未知的 Agent 会被 Cloudflare 拦截 — 包括合法的 Agent - 没有人类在循环中点击“允许” MCP 的 OAuth 2.1 规范是为**人类委托**认证(浏览器 → 重定向 → 用户点击允许)而构建的。它不涵盖**自主 Agent 身份** — 即在没有人类参与循环时 Agent 携带的凭证。 UBAG 填补了这一空白。 ## 工作原理 对启用了 UBAG 的站点的每一个请求都会通过一个 3 分支矩阵进行路由: ``` Incoming request │ ▼ ┌───────────────────┐ │ UBAG middleware │ └───────────────────┘ │ ├── Has valid UBAG credential? ──► Branch B: Clean JSON-LD data │ Structured. No HTML parsing. │ ├── Looks human? ───────────────► Branch A: Transparent proxy │ Origin server, untouched. │ └── Unknown agent? ─────────────► Branch C: Sandbox + challenge Sign a nonce with your Ed25519 key. Prove identity → get credentialed. ``` **分支 B 是核心洞见。** Agent 无需抓取 50 个页面来了解一家企业,UBAG 直接提供一个结构化的 JSON-LD 响应 — 产品、价格、政策、联系方式。一次请求,无需 HTML 解析,提取错误大幅减少。 ## 安全模型 UBAG 是**非对称的 — 身份路径中没有共享密钥:** - **Agent 身份 = Ed25519 密钥对。** Agent 的身份是其公钥的 SHA-256 指纹(`ubag:…`)。为了进入,Agent 使用其*私钥*对站点的 nonce 进行签名;站点使用*公钥*进行验证。只有密钥持有者才能通过 — 仅仅知道共享密钥永远无法确立 Agent *到底是谁*。 - **凭证 = ES256 JWT**,由颁发者的 EC P-256 私钥签名,并且任何站点都可以使用颁发者的*公钥*进行验证 — 通过 `/.well-known/jwks.json` 自动作为 JWKS 提供。任何站点都不需要密钥来验证凭证 — 这与 OAuth / OIDC 模型相同,正是这种模型允许一个凭证在独立的站点间通用。 - **支持所有权证明。** 每个凭证通过 `cnf` 声明绑定到 Agent 的密钥,因此验证者可以要求持有者证明它仍然持有匹配的私钥。 - **一个服务端 HMAC**,仅用于让站点确认它颁发了给定的 nonce **而无需存储状态**(服务器向*自身*签名)。它*不是*身份证明的一部分。 Python 和 Node SDK 共享相同的传输格式(原始 Ed25519 + ES256),因此其中一个产生的签名或凭证在另一个中可以进行逐字节验证。这种互操作性已通过两个包中的测试进行了覆盖。 ## 安装 尚未发布到 PyPI / npm。请从本仓库安装: ``` # Python (FastAPI / Starlette) git clone https://github.com/mohameduk/Ubag_protocol cd Ubag_protocol/ubag-python pip install -e ".[fastapi]" # Node (Express) cd ../ubag-node npm install ``` ## 快速开始 — Python (FastAPI) ``` from fastapi import FastAPI from ubag import UBAGMiddleware, generate_issuer_keypair # 你的站点是其自身的 credential issuer。生成一次并持久化这些凭证 # (或者通过单独传递 issuer_public_key 来运行 verify-only)。 ISSUER_PRIVATE, ISSUER_PUBLIC = generate_issuer_keypair() # EC P-256 (ES256) app = FastAPI() app.add_middleware( UBAGMiddleware, origin="https://yoursite.com", # Branch A proxy target issuer_key=ISSUER_PRIVATE, # mints + verifies agent credentials server_secret="a-random-32+char-string-for-nonce-stamping", site_meta={"name": "My Store", "type": "Store", "description": "We sell widgets"}, ) ``` `issuer_key` 也可以来自 `UBAG_ISSUER_KEY` 环境变量;仅验证部署可以单独传递 `issuer_public_key`(或 `UBAG_ISSUER_PUBLIC`)。 你的站点现在将: - ✅ 向已认证的 MCP Agent 提供纯净的 JSON-LD(分支 B) - ✅ 将人类透明地代理到你的源站(分支 A) - ✅ 使用 Ed25519 nonce 挑战对未知 Agent 进行沙盒隔离(分支 C) - ✅ 提供 `yoursite.com/.well-known/ubag.json` 用于 Agent 发现 - ✅ 在每次访问时调用可选的 `audit_fn(branch, request, response)` ## 快速开始 — Node (Express) ``` const express = require('express'); const { ubag, generateIssuerKeypair } = require('ubag'); const { privateKey: ISSUER_PRIVATE } = generateIssuerKeypair(); // EC P-256 (ES256) const app = express(); app.use(ubag({ origin: 'https://yoursite.com', issuerKey: ISSUER_PRIVATE, serverSecret: 'a-random-32+char-string-for-nonce-stamping', siteMeta: { name: 'My Store', type: 'Store', description: 'We sell widgets' }, })); ``` ## 查看运行效果(60 秒) 可运行的端到端演示会在进程内启动一个 UBAG 站点,并引导一个 Agent 完成整个握手过程 — *被拦截 → 受到挑战 → 对 nonce 签名 → 获得凭证 → 被提供 JSON-LD* — 然后打印出另一个站点将用于验证该凭证的 JWKS: ``` # Python cd ubag-python && pip install -e ".[fastapi]" && python ../examples/demo.py # Node npm install --prefix ubag-node && node examples/demo.js ``` ## 致 MCP Agent 开发者 如果你正在构建一个访问网站的 MCP Agent,请获取一个 UBAG 凭证: ``` from ubag import AgentCredential # 你的 agent 的身份就是它的 Ed25519 keypair。生成一次;持久化 agent.export()。 agent = AgentCredential.generate(owner="you@email.com") # 当 UBAG 站点向你发起 challenge (HTTP 429) 时,请对 nonce 进行签名并将其发回: # challenge = resp.json()["ubag_challenge"] # nested in the 429 body: nonce, timestamp, stamp # solution = agent.solve_challenge(challenge) # signs the nonce with your private key # r = httpx.post(f"{site}/ubag/verify", json=solution) # agent.set_credential(r.json()["credential"]) # 一旦获取 credential,它将随每个请求一起发送: headers = agent.headers() # {"X-UBAG-Credential": "eyJ..."} ``` 启用了 UBAG 的站点会识别你的 Agent,并直接提供结构化数据而非 HTML。你的 Agent 能获得更好的数据;网站所有者也能获得可见性和控制权。Node SDK 暴露了相同的 `AgentCredential` API。 ## 发现:`/.well-known/ubag.json` 每个启用了 UBAG 的站点都会在 `/.well-known/ubag.json` 提供一份发现文档 (保留 `/agents.json` 作为旧版别名)。这是刻意**不**命名为 `agents.json` 的 — 该文件名已被不相关的规范(Wildcard 的 OpenAPI 风格 `agents.json`、Google/Microsoft/HF 的 ARD 等)占用;`ubag.json` 使 UBAG 的身份/路由文档保持零冲突且明确无歧义。 ``` { "ubag_version": "1.0", "host": "yoursite.com", "credential_endpoint": "https://yoursite.com/ubag/verify", "branches": { "B-AGENT": { "description": "Authorized MCP agents — clean JSON-LD", "requires": "X-UBAG-Credential header with valid JWT", "content_type": "application/ld+json" }, "A-HUMAN": { "description": "Human browsers — transparently proxied to origin", "requires": "None" }, "C-SANDBOX": { "description": "Unknown agents — Ed25519 nonce challenge", "requires": "None — solve challenge to get credentialed", "challenge_endpoint": "/ubag/verify" } }, "discovery": { "ubag_json": "https://yoursite.com/.well-known/ubag.json", "verify_endpoint": "https://yoursite.com/ubag/verify", "jwks_endpoint": "https://yoursite.com/.well-known/jwks.json" } } ``` 就像 `robots.txt` 一样,但可被机器执行 — Agent 会在发起请求前获取它。 ## 为什么不直接使用 Cloudflare? | | Cloudflare | AWS WAF | UBAG | |---|---|---|---| | 阻止未知 bot | ✅ | ✅ | 对它们进行挑战 | | 为 Agent 提供结构化数据 | Markdown(AI 功能) | ❌ | ✅ JSON-LD | | 加密 Agent 身份 / 凭证 | ❌ | ❌ | ✅ | | 自主 Agent 支持(无浏览器) | ❌ | ❌ | ✅ | | 开源 | ❌ | ❌ | ✅ | | 供应商锁定 | Cloudflare | AWS | 无 | Cloudflare 和 AWS 会阻止或过滤 bot。UBAG 则是**提升**它们:一个未知的 Agent 可以解决挑战、获得凭证并变得已授权 — 没有任何合法 Agent 会被永久阻止。*(竞争对手列反映了撰写本文时的一般功能;请对照当前的供应商文档进行验证。)* ## MCP 集成 UBAG 是对 MCP 的补充,而不是替代它: - **MCP OAuth 2.1** — 人类委托认证(用户在浏览器中点击允许) - **UBAG 凭证** — 自主 Agent 身份(无人类在循环中) ``` MCP Agent │ ├── Talking to MCP servers? ──► MCP OAuth 2.1 │ └── Visiting websites? ────────► UBAG credential ``` UBAG 凭证只需颁发一次,并由站点的 middleware 在进程内进行验证 — 无需重定向,无需浏览器流程 — 并且可在任何启用了 UBAG 的站点上工作。 ## 仓库布局 ``` ubag-python/ Python middleware — FastAPI / Starlette today (v0.2.0) ubag-node/ Node middleware — Express today (v0.2.0) ``` 这两个包都实现了完整的协议(路由、凭证、挑战、密钥、 ubag.json)并共享一个可交叉验证的传输格式。 ## 运行测试 ``` # Python cd ubag-python && pip install -e ".[dev]" && pytest # Node cd ubag-node && npm install && npm test ``` ## 项目状态 **目前已实现** - [x] 分支 A — 人类透明代理 - [x] 分支 B — Agent JSON-LD 结构化数据 - [x] 分支 C — 沙盒 + Ed25519 nonce 挑战 - [x] 非对称加密 — Ed25519 Agent 身份 + ES256/JWKS 凭证,无共享密钥 - [x] `ubag.json` 发现 — 在每个 UBAG 站点上提供(别名:`/agents.json`) - [x] 审计钩子 — 在每次请求时调用 `audit_fn` 回调 - [x] Python SDK (FastAPI/Starlette) + Node SDK (Express),已实现跨 SDK 验证 **计划中 / 尚未构建** - [ ] 发布到 PyPI (`pip install ubag`) 和 npm (`npm install ubag`) - [ ] Django / Flask / Next.js middleware 适配器 - [ ] 托管凭证注册表 / 颁发者位于 `ubagprotocol.com/credential` - [ ] WordPress 插件 - [ ] Docker 参考部署(一键自托管) - [ ] 正式规范文档 (`docs/spec/…`) - [ ] 面向站点所有者的支付/收入分成层 ## 联系方式 由 Mohamed Ben Hadj Hmida 构建 [ubagprotocol.com](https://ubagprotocol.com) · [github.com/mohameduk/Ubag_protocol](https://github.com/mohameduk/Ubag_protocol) MIT 许可证。
标签:AI代理, GNU通用公共许可证, MITM代理, Node.js, Python, Web网关, 无后门, 路由控制, 逆向工具