
Ein transparenter PII-Redaktions-Proxy für LLM-API-Traffic. Er sitzt zwischen einer Anwendung und einem LLM-Anbieter (derzeit Anthropic), pseudonymisiert sensible Daten ausgehend und stellt sie eingehend wieder her. Erstellt mit FastAPI + httpx.
Ein transparenter PII-Schutzproxy für LLM-API-Traffic. Er sitzt zwischen Ihrer Anwendung und dem LLM-Anbieter, pseudonymisiert sensible Daten auf dem Hinweg und stellt sie auf dem Rückweg wieder her.
Ihr LLM sieht niemals echte Namen, E-Mails, IPs oder Domains – es arbeitet ausschließlich mit strukturierten Pseudonymen wie [email protected]. Ihre Anwendung erhält die ursprünglichen Werte transparent zurück.
Bei der Verwendung von LLMs für Sicherheitsoperationen, Incident Response oder andere Aufgaben mit echten Kundendaten besteht das Risiko, dass PII an Drittanbieter-APIs gesendet wird. Dieser Proxy löst das Problem durch:
# 1. Erstellen Sie Ihre Konfiguration
cp config.json.example config.json
# Bearbeiten Sie config.json mit Ihren internen Domains, bekannten Entitäten usw.
# 2. Mit Docker ausführen
docker build -t llm-token-proxy .
docker run -p 8090:8080 -v ./config.json:/app/config.json llm-token-proxy
# 3. Leiten Sie Ihre Anwendung an den Proxy weiter
export ANTHROPIC_BASE_URL=http://localhost:8090/session/my-session/
Das war's. Ihre Anthropic-API-Aufrufe laufen jetzt durch den Proxy mit geschwärzter PII.

Typischer Ablauf: Anwendung → Token Proxy (PII-Schwärzung) → LLM-API (nur Pseudonyme) → Token Proxy (Originale wiederherstellen) → Anwendung
admin aus [email protected])Pseudonyme sind innerhalb einer Sitzung deterministisch – derselbe reale Wert wird immer auf dasselbe Pseudonym abgebildet.
Wenn ein LLM Sicherheitsprotokolle analysiert, spielen der Hosting-Anbieter und die Geolokalisierung einer IP-Adresse eine Rolle – ein Login von einer Hetzner-IP in Deutschland erzählt eine andere Geschichte als einer von einem Residential-ISP in den USA. Eine naive Ersetzung durch Dokumentationsbereichs-IPs (z.B. 198.51.100.x) zerstört diesen Kontext.
Mit der optionalen MaxMind GeoLite2-ASN-Datenbank ersetzt der Proxy echte IPs durch eine andere IP aus derselben ASN und demselben Subnetz. Das LLM sieht eine real aussehende IP, die zum selben Hosting-Anbieter und annähernd gleichen geografischen Gebiet auflöst – aber es ist nicht die tatsächliche Adresse.
10.99.99.x abgebildet (kein ASN-Kontext zu erhalten)198.51.100.x zurück (Dokumentationsbereich)Die Spender-IP wird deterministisch per HMAC mit einem sitzungsspezifischen Salt gewählt, sodass dieselbe echte IP innerhalb einer Sitzung immer auf denselben Spender abgebildet wird, verschiedene Sitzungen jedoch unterschiedliche Zuordnungen erzeugen.
Der Proxy wird mit einer leeren config.json ausgeliefert – keine eingebauten Wortlisten oder domänenspezifischen Annahmen. Die mitgelieferte config.json.example ist für Sicherheitsoperationen mit Microsoft Sentinel und Entra ID optimiert (über 8.000 KQL-Tabellen-/Spaltennamen, Graph-API-Berechtigungsbegriffe, Sicherheitsreferenzdomains). Falls dies Ihrem Anwendungsfall entspricht, kopieren Sie, was Sie benötigen. Wenn Sie den Proxy für einen anderen Bereich (Gesundheitswesen, Recht, Finanzen usw.) verwenden, beginnen Sie mit der leeren Konfiguration und erstellen Sie Ihre eigenen Listen.
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_-Pseudonyme)spacy + en_core_web_sm)false wird der Proxy zum reinen Durchlassfalse werden Domains unverändert durchgelassen (E-Mails, IPs, Namen werden weiterhin geschwärzt). Nützlich, wenn Domainnamen wichtige Kontextinformationen für das LLM liefern (z. B. Unterscheidung von outlook.com und protonmail.com) und nicht als sensibel gelten.Verwalten Sie Whitelists und schalten Sie die Schwärzung ohne Neustart um:
# Alle Whitelists anzeigen
curl http://localhost:8090/token-proxy/config/whitelist
# Begriffe zur NER-Skiplist hinzufügen (reduziert False Positives)
curl -X POST http://localhost:8090/token-proxy/config/whitelist \
-H "Content-Type: application/json" \
-d '{"category": "ner_skiplist", "values": ["EvoSTS", "Hetzner"]}'
# Domains zur Allowlist hinzufügen (diese werden nie pseudonymisiert)
curl -X POST http://localhost:8090/token-proxy/config/whitelist \
-H "Content-Type: application/json" \
-d '{"category": "domain_allowlist", "values": ["github.com"]}'
# Schwärzung deaktivieren (Durchlassmodus)
curl -X POST http://localhost:8090/token-proxy/config/status \
-H "Content-Type: application/json" \
-d '{"redaction_enabled": false}'
Whitelist-Kategorien: ner_skiplist, domain_allowlist, known_persons, known_orgs, known_hostnames
Überprüfen Sie in Echtzeit, was der Proxy tut:
# Aktive Sitzungen auflisten
curl http://localhost:8090/token-proxy/sessions
# Pseudonymzuordnungen für eine Sitzung anzeigen
curl http://localhost:8090/token-proxy/sessions/{session_id}/mappings
# Protokoll der Schwärzungsaktivitäten anzeigen
curl http://localhost:8090/token-proxy/sessions/{session_id}/log
# Zuordnungen durchsuchen
curl http://localhost:8090/token-proxy/sessions/{session_id}/search?q=admin
# Erfasste Payloads anzeigen (was das LLM tatsächlich gesehen hat)
curl http://localhost:8090/token-proxy/sessions/{session_id}/payloads
# Token-Nutzung für eine Sitzung (Eingabe-/Ausgabetoken über alle Anfragen)
curl http://localhost:8090/token-proxy/sessions/{session_id}/usage
# Globale Statistiken (enthält total_tokens über alle Sitzungen hinweg)
curl http://localhost:8090/token-proxy/stats
Der Proxy zeichnet input_tokens und output_tokens für jede weitergeleitete Anfrage auf – sowohl für Non-Streaming (aus dem Antwort-usage-Objekt gelesen) als auch für Streaming (aus message_start- und message_delta-SSE-Ereignissen geparst). Da der Proxy zwischen Ihrer Anwendung und dem LLM sitzt, erhalten Sie einen einzigen Engpass zur Messung des Verbrauchs aller Clients, die ihn gemeinsam nutzen, ohne jeden einzelnen instrumentieren zu müssen.
curl http://localhost:8090/token-proxy/sessions/my-session/usage
# {
# "session_id": "my-session",
# "request_count": 3,
# "input_tokens": 1240,
# "output_tokens": 587
# }
curl http://localhost:8090/token-proxy/stats | jq .total_tokens
# { "input_tokens": 48213, "output_tokens": 19044 }
Die Nutzung pro Anfrage ist auch in /token-proxy/sessions/{session_id}/log unter usage_counts enthalten. Es werden nur rohe Token-Anzahlen verfolgt – die Preisgestaltung bleibt dem Aufrufer überlassen.
Der Proxy unterstützt SSE-Streaming (stream: true). Pseudonyme werden in Echtzeit mit einem Tail-Buffer-Ansatz wiederhergestellt, der über SSE-Blöcke verteilte Pseudonyme verarbeitet.
Der Proxy verwendet ein Provider-Adapter-Muster. Derzeit wird unterstützt:
/v1/messages)Siehe CONTRIBUTING.md für Informationen zum Hinzufügen von Unterstützung für weitere Anbieter (OpenAI, Google Gemini usw.).
en_core_web_sm) erkennt englische Personen-/Organisationsnamen. Namen in anderen Sprachen können übersehen werden, es sei denn, sie werden in der Konfiguration unter known_persons/known_orgs hinzugefügt.admin [at] acme.com, Telefonnummern, physische Adressen) werden nicht erfasst. Die Erkennungspipeline ist auf strukturierte IT-/Sicherheitsdaten abgestimmt./token-proxy/config/* und /token-proxy/sessions/* haben keine Authentifizierung. Der Proxy ist für vertrauenswürdige/interne Netzwerke ausgelegt – setzen Sie diese Endpunkte keinen unsicheren Netzwerken aus.# Entwicklungsabhängigkeiten installieren
pip install -e ".[dev,ner]"
python -m spacy download en_core_web_sm
# Tests ausführen
pytest
# Lint
ruff check token_proxy/ tests/
Apache 2.0 – siehe LICENSE.
| Entitätstyp | Internes Beispiel | Externes Beispiel |
|---|
[email protected] | [email protected] | |
| Domain | domain-internal-001.com | domain-external-001.net |
| IP | 10.99.99.1 (RFC1918) | ASN-bewusste Spender-IP (siehe unten) |
| Person | person_internal_001 | person_external_001 |
| Organisation | org_internal_001 | org_external_001 |
| Hostname | host_001 | host_001 |
| Variable | Standard | Zweck |
|---|
ANTHROPIC_API_BASE | https://api.anthropic.com | Upstream-Anthropic-API-URL |
TOKEN_PROXY_CONFIG_PATH | /app/config.json | Pfad zur Konfigurationsdatei |
LOG_LEVEL | info | Protokollierungsebene |
GEOIP_ASN_DB_PATH | /app/data/GeoLite2-ASN.mmdb | MaxMind-GeoLite2-ASN-Datenbank (optional) |