NagaYu/local-pii-masking-api
GitHub: NagaYu/local-pii-masking-api
一个 100% 本地运行、零出口流量的 PII 脱敏与还原代理 API,用于在文本发送到云端 LLM 之前保护敏感个人数据。
Stars: 0 | Forks: 0
# 本地安全 Tokenizer 与 PII 脱敏 API
[](https://github.com/NagaYu/local-pii-masking-api/actions/workflows/ci.yml)
[](https://github.com/NagaYu/local-pii-masking-api/actions/workflows/docker-publish.yml)
[](https://hub.docker.com/r/yuta713/local-pii-masking-api)
[](LICENSE)
[](https://www.python.org/)
一个 **100% 本地设备运行的无头代理 API**,能够检测原始文本中的个人身份信息 (PII),并将其替换为确定性、可逆的 token —— 然后在返回时还原原始内容。
将它部署在任何外部 LLM(或任何第三方 API)的前端,即可构建一道坚固的**安全墙**:对外发的 prompt 进行脱敏,仅将 token 发送到云端,然后在本地对模型的回复进行还原。**您的敏感数据在物理上绝对不会离开宿主机。**
## 设计原则
| 原则 | 含义 |
| --- | --- |
| **100% 数据驻留** | 检测和 token 化完全在本地 CPU 上运行,使用正则表达式和轻量级验证器。该服务自身**不发起任何出站网络调用**。 |
| **零知识网关代理** | token ↔ 原始内容的映射仅存在于进程内存中,并按会话划分作用域。下游系统(LLM、日志、分析)永远只能看到像 `[MASKED_EMAIL_1]` 这样的不透明 token。 |
| **零外部基础设施成本** | 无需数据库、消息队列、云服务或模型下载。单个 container 即为完整的部署。 |
| **确定性与可逆** | 在同一个会话中,相同的值始终产生相同的 token(从而保持 LLM prompt 的连贯性),并且每个 token 都能精确映射回其原始子字符串。 |
| **内存受限** | 会话存储库会过期 (TTL),并发会话数量受 LRU 驱逐机制限制,且每个存储库都有大小上限 —— 因此持续的高吞吐量文档流不会导致内存泄漏。 |
## 检测范围
| 类别 | Token 示例 | 备注 |
| --- | --- | --- |
| 电子邮箱地址 | `[MASKED_EMAIL_1]` | |
| 电话号码 | `[MASKED_PHONE_1]` | 7–15 位数字,支持国际/美国分组 |
| 信用卡号 | `[MASKED_CREDIT_CARD_1]` | 通过 **Luhn** 校验和确认 |
| IBAN | `[MASKED_IBAN_1]` | |
| 美国 SSN | `[MASKED_SSN_1]` | |
| IP 地址 | `[MASKED_IP_ADDRESS_1]` | IPv4,经过八位组验证 |
| URL | `[MASKED_URL_1]` | |
| 人名 | `[MASKED_PERSON_1]` | 启发式检测,仅限 **strict** 级别 |
| 邮政地址 | `[MASKED_ADDRESS_1]` | 启发式检测,仅限 **strict** 级别 |
### 严格级别
- **`lenient`** — 仅检测明确的标识符(电子邮箱、信用卡、IBAN、SSN)。
- **`standard`** *(默认)* — lenient 集合 **+** 电话号码、IP 地址、URL。
- **`strict`** — standard 集合 **+** 启发式的人名和地址检测
(召回率最高,但可能产生误报)。
## 快速开始(3 分钟)
### 选项 A — Docker(推荐)
拉取预构建的镜像(支持多架构:`linux/amd64`, `linux/arm64`):
```
docker run --rm -p 8080:8080 yuta713/local-pii-masking-api:latest
```
…或者从源码在本地构建:
```
docker build -t local-pii-api .
docker run --rm -p 8080:8080 local-pii-api
```
### 选项 B — 本地 Python (3.10+)
```
python -m venv .venv && source .venv/bin/activate
pip install -r requirements.txt
uvicorn app.main:app --host 127.0.0.1 --port 8080
```
然后打开交互式的全英文 API 文档:
- **Swagger UI:** http://127.0.0.1:8080/docs
- **健康检查:** http://127.0.0.1:8080/health
运行测试套件:
```
pip install -r requirements-dev.txt
pytest -q
```
## API 参考
### `POST /api/v1/mask`
**请求**
```
{
"text": "Contact John Doe at john.doe@acme.com or +1 (415) 555-0132.",
"strictness": "standard",
"client_id": "support-bot-01",
"session_id": null
}
```
**响应**
```
{
"masked_text": "Contact John Doe at [MASKED_EMAIL_1] or [MASKED_PHONE_1].",
"session_id": "1c4f0b9e7c3a4a9e9d2f3a1b2c3d4e5f",
"detections": 2,
"detections_by_type": { "EMAIL": 1, "PHONE": 1 },
"latency_ms": 0.19
}
```
### `POST /api/v1/unmask`
**请求**
```
{
"text": "I've emailed [MASKED_EMAIL_1] and called [MASKED_PHONE_1].",
"session_id": "1c4f0b9e7c3a4a9e9d2f3a1b2c3d4e5f"
}
```
**响应**
```
{
"unmasked_text": "I've emailed john.doe@acme.com and called +1 (415) 555-0132.",
"restored": 2,
"latency_ms": 0.02
}
```
如果会话未知或已过期,则返回 **404**(原始内容已无法恢复;需重新对源文本进行脱敏)。
### `GET /health`
```
{ "status": "ok", "version": "1.0.0", "active_sessions": 3, "uptime_seconds": 1287.4 }
```
## 作为云端 LLM 前端的安全墙使用
该模式始终是相同的三个步骤:**mask → 调用云端 → unmask**。
```
import requests
GATEWAY = "http://127.0.0.1:8080"
raw_prompt = (
"Summarize this ticket from John Doe (john.doe@acme.com, "
"+1 (415) 555-0132): the customer cannot log in."
)
# 1) 在本地 MASK — 在任何数据离开大楼之前剥离 PII。
m = requests.post(
f"{GATEWAY}/api/v1/mask",
json={"text": raw_prompt, "client_id": "ticket-summarizer"},
).json()
safe_prompt = m["masked_text"] # contains only tokens, no PII
session_id = m["session_id"]
# 2) 仅使用已净化的 prompt CALL THE CLOUD。
# (将其替换为您提供商的 SDK / HTTP 调用)
cloud_reply = call_your_favorite_cloud_llm(safe_prompt)
# 例如 -> "I've drafted a reply to [MASKED_EMAIL_1] about the login issue."
# 3) 在本地 UNMASK 响应以恢复真实值。
u = requests.post(
f"{GATEWAY}/api/v1/unmask",
json={"text": cloud_reply, "session_id": session_id},
).json()
print(u["unmasked_text"])
# -> "I've drafted a reply to john.doe@acme.com about the login issue."
```
```
# 使用 curl 的相同流程:
curl -s -X POST http://127.0.0.1:8080/api/v1/mask \
-H "Content-Type: application/json" \
-d '{"text":"Email john.doe@acme.com","client_id":"cli"}'
```
## 配置
所有设置均为环境变量,并提供生产安全的默认值:
| 变量 | 默认值 | 描述 |
| --- | --- | --- |
| `PORT` | `8080` | 监听端口(container)。 |
| `PII_SESSION_TTL_SECONDS` | `3600` | 会话存储库在被清除前的空闲生命周期。 |
| `PII_MAX_SESSIONS` | `10000` | 最大并发存储库;超出此数量时将驱逐最旧(LRU)的存储库。 |
| `PII_MAX_ENTRIES_PER_SESSION` | `50000` | 每个存储库可存储的最大不同值数量。 |
| `PII_SWEEP_INTERVAL_SECONDS` | `60` | 后台清理程序清除过期存储库的频率。 |
## 范围与限制
本项目是一个**开源 MVP / 参考实现**。它在设计上有意保持轻量和极少的依赖。在依赖它之前,请了解以下边界:
- **单进程状态。** 会话存储库存在于单个进程的内存中。
请使用**单个 worker** 运行(默认设置)。运行多个 Uvicorn/Gunicorn
worker —— 或多个副本 —— 会将 `mask` 和 `unmask` 路由到不同的
进程,从而破坏还原机制。横向扩展需要共享存储(例如 Redis);这超出了本项目的范围。
- **以英语/美国为中心的检测。** 检测器针对电子邮件、电话、信用卡、IBAN、SSN、IP、URL 以及(启发式地)英文姓名和美国地址。它们**不**涵盖特定语言环境的标识符,例如日本的 My Number(个人编号)、日本的电话/邮政编码格式或非拉丁字母姓名。
- **基于正则表达式的尽力而为。** 检测以牺牲完整性来换取速度和零依赖。预期会出现漏报和误报,尤其是在启发式的 `strict` 级别姓名/地址检测器中。这是一种纵深防御,**而非**合规保证。
- **无内置身份验证或速率限制。** 请将其部署在您自己的身份验证/网关之后,并保持在受信任的本地/专用网络中。
## 安全说明
- **无出站流量。** 该服务从不发起外部连接。您可以将其运行在气隙网络中,或者完全阻断其出站防火墙。
- **CORS 已被锁定**,仅限回环地址和 RFC-1918 私有网段
(`localhost`, `127.0.0.0/8`, `10/8`, `172.16/12`, `192.168/16`, `[::1]`)。
绝对不允许任何公共来源访问。
- **纯内存映射。** Token ↔ 原始内容的映射永远不会写入磁盘。重启进程后,所有机密信息都会随之消失。
- **纵深防御,而非万灵药。** 启发式检测器(姓名、
地址)以牺牲精确度来换取召回率。请选择适合您风险承受能力的严格级别,并将此网关置于您自己的身份验证之后。
## 架构
```
┌─────────────────────────── your host / private LAN ───────────────────────────┐
│ │
raw text ──┼──► POST /api/v1/mask ──► engine.py (regex + Luhn, 100% local) │
│ │ │
│ ▼ │
│ in-memory session vault (TTL + LRU bounded) │
│ │ │
tokens ◄──┼──────────────────────────────┘ │
│ │ │
│ └──► (you send tokens to any external LLM — no PII crosses the boundary) │
│ │
LLM reply ─┼──► POST /api/v1/unmask ──► restore via vault ──► original values returned │
│ │
└────────────────────────────────────────────────────────────────────────────────┘
```
| 文件 | 职责 |
| --- | --- |
| `app/schemas.py` | 严格的 Pydantic v2 请求/响应契约与验证。 |
| `app/engine.py` | 设备端 PII 检测器、确定性 tokenizer、有界存储库。 |
| `app/main.py` | FastAPI 应用:CORS 锁定、`/health`、`/mask`、`/unmask`、OpenAPI 文档。 |
| `tests/test_api.py` | 单元测试与 HTTP 集成测试(检测、往返测试、内存边界)。 |
| `Dockerfile` | 多阶段、非 root 用户、带有健康检查的生产级镜像。 |
## 许可证
基于 [MIT 许可证](LICENSE) 发布。
标签:API代理, AV绕过, DLL 劫持, FastAPI, Python, 大语言模型, 数据脱敏, 无后门, 网络安全, 请求拦截, 逆向工具, 隐私保护