
Прозрачный прокси-сервер для редактирования PII в трафике API LLM. Располагается между приложением и поставщиком LLM (в настоящее время Anthropic), псевдонимизируя конфиденциальные данные при исходящем трафике и восстанавливая их при входящем. Создан с использованием FastAPI + httpx.
Прозрачный прокси для редактирования PII в трафике LLM. Располагается между вашим приложением и провайдером LLM, псевдонимизируя конфиденциальные данные на пути к LLM и восстанавливая их на обратном пути.
Ваша LLM никогда не видит реальных имён, адресов электронной почты, IP-адресов или доменов — она работает исключительно со структурированными псевдонимами, такими как [email protected]. Ваше приложение получает обратно исходные значения прозрачным образом.
При использовании LLM для задач безопасности, реагирования на инциденты или любых других задач, связанных с реальными данными клиентов, вы рискуете отправить PII сторонним API. Этот прокси решает проблему следующим образом:
# 1. Создайте свой конфигурационный файл
cp config.json.example config.json
# Отредактируйте config.json: укажите внутренние домены, известные сущности и т.д.
# 2. Запустите с Docker
docker build -t llm-token-proxy .
docker run -p 8090:8080 -v ./config.json:/app/config.json llm-token-proxy
# 3. Направьте ваше приложение на прокси
export ANTHROPIC_BASE_URL=http://localhost:8090/session/my-session/
Всё. Теперь вызовы Anthropic API проходят через прокси с отредактированными PII.

Типичный поток: Приложение → Token Proxy (редактирование PII) → LLM API (только псевдонимы) → Token Proxy (восстановление оригиналов) → Приложение
admin из [email protected])| Тип сущности | Внутренний пример | Внешний пример |
|---|---|---|
[email protected] | [email protected] | |
| Домен | domain-internal-001.com | domain-external-001.net |
| IP | 10.99.99.1 (RFC1918) | ASN-ассоциированный донорский IP (см. ниже) |
| Лицо | person_internal_001 | person_external_001 |
| Организация | org_internal_001 | org_external_001 |
| Имя хоста | host_001 | host_001 |
Псевдонимы являются детерминированными в рамках сессии — одно и то же реальное значение всегда сопоставляется с одним и тем же псевдонимом.
Когда LLM анализирует журналы безопасности, провайдер хостинга и геолокация IP-адреса имеют значение — вход с IP Hetzner в Германии говорит об ином, чем вход с домашнего провайдера в США. Наивная замена на IP из документационных диапазонов (например, 198.51.100.x) уничтожает этот контекст.
С опциональной базой MaxMind GeoLite2-ASN прокси заменяет реальные IP на другой IP из той же ASN и подсети. LLM видит реально выглядящий IP, который относится к тому же провайдеру хостинга и примерной географии — но это не настоящий адрес.
10.99.99.x (контекст ASN отсутствует)198.51.100.x (диапазон документации)Донорский IP выбирается детерминированно через HMAC с солью сессии, поэтому один и тот же реальный IP всегда сопоставляется с одним и тем же донором в рамках сессии, но разные сессии дают разные сопоставления.
Прокси поставляется с пустым config.json — никаких встроенных списков слов или доменных предположений. Прилагаемый config.json.example настроен для задач безопасности с Microsoft Sentinel и Entra ID (более 8000 имён таблиц/столбцов KQL, терминов разрешений Graph API, эталонных доменов безопасности). Если это соответствует вашему варианту использования, скопируйте нужное из него. Если вы используете прокси для другой области (здравоохранение, юриспруденция, финансы и т.д.), начните с пустого конфига и создайте свои собственные списки.
config.json{
"internal_domains": ["yourcompany.com"],
"partner_domains": ["partnercorp.com"],
"internal_ip_ranges": ["10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"],
"known_persons": ["John Smith"],
"known_orgs": ["YourCompany"],
"known_hostnames": ["DC01", "FS01"],
"ner_enabled": true,
"ner_skiplist": [],
"redaction_enabled": true
}
_internal_)spacy + en_core_web_sm)false прокси становится чистым сквозным каналомfalse домены проходят без изменений (email, IP, имена всё равно редактируются). Полезно, когда имена доменов несут важный контекст для LLM (например, различие outlook.com и protonmail.com) и не считаются конфиденциальными.| Переменная | Значение по умолчанию | Назначение |
|---|---|---|
ANTHROPIC_API_BASE | https://api.anthropic.com | URL вышестоящего Anthropic API |
TOKEN_PROXY_CONFIG_PATH | /app/config.json | Путь к конфигурационному файлу |
LOG_LEVEL | info | Уровень логирования |
GEOIP_ASN_DB_PATH | /app/data/GeoLite2-ASN.mmdb | База данных MaxMind GeoLite2-ASN (опционально) |
Управляйте белыми списками и переключайте редактирование без перезапуска:
# Просмотр всех белых списков
curl http://localhost:8090/token-proxy/config/whitelist
# Добавление терминов в списки игнорирования NER (уменьшает ложные срабатывания)
curl -X POST http://localhost:8090/token-proxy/config/whitelist \
-H "Content-Type: application/json" \
-d '{"category": "ner_skiplist", "values": ["EvoSTS", "Hetzner"]}'
# Добавление доменов в разрешённый список (никогда не псевдонимизировать)
curl -X POST http://localhost:8090/token-proxy/config/whitelist \
-H "Content-Type: application/json" \
-d '{"category": "domain_allowlist", "values": ["github.com"]}'
# Отключение редактирования (режим сквозной передачи)
curl -X POST http://localhost:8090/token-proxy/config/status \
-H "Content-Type: application/json" \
-d '{"redaction_enabled": false}'
Категории белых списков: ner_skiplist, domain_allowlist, known_persons, known_orgs, known_hostnames
Просматривайте, что делает прокси в реальном времени:
# Список активных сессий
curl http://localhost:8090/token-proxy/sessions
# Просмотр сопоставлений псевдонимов для сессии
curl http://localhost:8090/token-proxy/sessions/{session_id}/mappings
# Просмотр журнала активности редактирования
curl http://localhost:8090/token-proxy/sessions/{session_id}/log
# Поиск сопоставлений
curl http://localhost:8090/token-proxy/sessions/{session_id}/search?q=admin