a4api 的核心工作对象是 API Key 与完整的模型对话流量,任何界面与功能的改动都不能削弱安全性。项目把「安全可靠」作为立身之本,从密钥存储、网络边界、配置写入、进程管控到日志隐私做了成体系的防护。本文章汇总全部安全机制的设计意图与实现位置,作为安全审计与使用信任的索引。
1. 防护全景
graph LR
A[威胁面] --> B[密钥泄露]
A --> C[未授权调用]
A --> D[配置损坏]
A --> E[恶意更新]
B --> F[DPAPI 加密存储
接口永不回显] C --> G[代理仅监听本机
随机 token 鉴权
CORS 白名单] D --> H[自动备份
原子写入
合并式更新] E --> I[清单签名验签
SHA256 校验
传输白名单] style A fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style B fill:#fadbd8,stroke:#c0392b,stroke-width:2px style C fill:#fadbd8,stroke:#c0392b,stroke-width:2px style D fill:#fadbd8,stroke:#c0392b,stroke-width:2px style E fill:#fadbd8,stroke:#c0392b,stroke-width:2px style F fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style G fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style H fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style I fill:#d5f5e3,stroke:#27ae60,stroke-width:2px
接口永不回显] C --> G[代理仅监听本机
随机 token 鉴权
CORS 白名单] D --> H[自动备份
原子写入
合并式更新] E --> I[清单签名验签
SHA256 校验
传输白名单] style A fill:#ebdef0,stroke:#8e44ad,stroke-width:2px style B fill:#fadbd8,stroke:#c0392b,stroke-width:2px style C fill:#fadbd8,stroke:#c0392b,stroke-width:2px style D fill:#fadbd8,stroke:#c0392b,stroke-width:2px style E fill:#fadbd8,stroke:#c0392b,stroke-width:2px style F fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style G fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style H fill:#d5f5e3,stroke:#27ae60,stroke-width:2px style I fill:#d5f5e3,stroke:#27ae60,stroke-width:2px
2. API Key 加密存储
- 所有 API Key 在入库前经 Windows DPAPI 加密——直接调用
crypt32.dll的CryptProtectData,无第三方依赖;密文以 base64 存入 SQLite,与当前 Windows 用户绑定,换用户或换机器后无法解密。 - 任何后端接口的响应都不包含 Key 明文或密文:序列化模型不暴露密钥字段,前端永远只显示「已设置」状态。
- 密钥仅在两个时机被解密使用:执行切换写入目标配置文件时、本地翻译代理按生效配置更新上游时。
- 解密失败时返回空字符串并记录错误日志,不静默产出脏数据。
- 非 Windows 环境仅做 base64 编码兜底,不具备安全性,仅供开发调试使用。
3. 本地翻译代理的边界
为 OpenAI 兼容服务商运行的本地翻译代理遵循最小暴露原则:
| 防护 | 取值 |
|---|---|
| 监听地址 | 仅 127.0.0.1,不对局域网或外网开放 |
| 端口范围 | 17890 - 17899 固定小段 |
| 鉴权 | 每次启动以加密随机数生成 token,请求必须携带且匹配,否则 401 |
| 密钥持有 | 从数据库按生效配置解密获得,进程内使用,不硬编码、不落盘明文 |
| 运行条件 | 仅当前生效配置需要代理时存活,否则数秒内自动退出 |
复用已运行代理前还会做能力握手校验,避免误用旧版本遗留的未鉴权进程。机制细节见本地翻译代理。
4. 配置写入完整性
用户最怕「切一次配置毁一套环境」,a4api 用三层机制保证写坏不可能发生:
| 层次 | 机制 |
|---|---|
| 事前 | 修改前自动备份原文件到数据目录,各类文件独立滚动保留最近 5 份 |
| 事中 | 合并式生成:只覆盖工具托管的字段,hooks、permissions、MCP 配置等原样保留 |
| 写入 | 原子替换:临时文件加 fsync 加操作系统级 replace,断电也不产生半截文件 |
配合切换前置的兼容性校验(目标与服务商协议不符时零写入返回),任何失败路径都不会留下半生效状态,详见配置方案与一键切换。
5. 后端接口防护
桌面形态下 FastAPI 只服务本机,但仍做了纵深防御:
- CORS 白名单仅放行
localhost、127.0.0.1与[::1],恶意网站无法跨域读取或篡改本地配置。 - 请求体强校验:Pydantic 模型约束字段类型与枚举(如协议类型仅允许 anthropic 或 openai),非法输入直接拒绝。
- 静态资源统一托管:前端由后端进程自己提供,不存在独立对外的静态服务器。
6. 数据目录与文件权限
- 打包运行时数据(数据库、备份)写入
%APPDATA%\a4api\,位于当前用户目录内,不写程序目录,规避多版本冲突与权限问题。 .gitignore排除数据库与运行时数据,密钥密文不会随仓库泄露。- 非 Windows 环境对数据目录与数据库文件执行
700/600权限收紧(尽力而为的加固,Windows 上由 NTFS ACL 控制)。
7. 并发与数据一致性
- 配置激活使用进程内互斥锁串行化,并发点击多张卡片也不会把两个方案同时标为生效。
- 异常路径事务回滚,数据库不留半写入状态。
- SQLite 连接统一开启外键约束(
PRAGMA foreign_keys=ON);删除服务商前校验其下配置方案数量,有引用则拒绝删除,杜绝孤儿数据。
8. 进程管控
- 以 Windows 命名互斥体保证桌面应用单实例运行,防止多实例互相覆盖配置。
- 重启 Claude Code 前用 CIM 精确匹配命令行包含 claude 的进程再结束,避免误杀无关进程。
9. 日志与隐私
- 默认日志不记录任何请求或响应内容,只有时间、级别与摘要,写入
~/.a4api/logs/。 - 含完整请求头、请求体与上游响应的调试日志默认关闭,仅在显式设置环境变量
A4API_PROXY_DEBUG时开启,排障后应关闭。
10. 更新链路防篡改
自动更新是远程攻击面,a4api 用「签名清单 + 内容哈希 + 传输白名单」三重校验保证装进来的安装包就是作者发布的那个:Ed25519 签名的更新清单、边下边算的 SHA256 比对、逐跳 HTTPS 主机白名单,外加严格防降级。完整机制见自动更新。
11. 测试保障
关键安全行为都有自动化回归测试守护:
| 测试文件 | 覆盖内容 |
|---|---|
test_crypto.py |
DPAPI 加解密往返、非法密文返回空 |
test_config_manager.py |
三端配置生成与合并、原子写入不留临时残留 |
test_openai_proxy.py |
Anthropic 与 Responses 协议翻译正确性、工具 schema 处理、null 归一回归 |
test_updater.py |
签名载荷基准、验签与篡改拒绝、版本比较与降级、SHA256 与尺寸校验、URL 白名单等 |
test_switch.py 等 |
切换流程、预置播种、配置接口的行为约束 |
举手提问