
Un proxy trasparente di redazione dei PII per il traffico API LLM. Si posiziona tra un'applicazione e un provider LLM (attualmente Anthropic), pseudonimizzando i dati sensibili in uscita e ripristinandoli in entrata. Realizzato con FastAPI + httpx.
Un proxy trasparente di oscuramento PII per il traffico API LLM. Si posiziona tra la tua applicazione e il provider LLM, pseudonimizzando i dati sensibili in uscita e ripristinandoli in entrata.
Il tuo LLM non vede mai nomi reali, email, IP o domini — lavora esclusivamente con pseudonimi strutturati come [email protected]. La tua applicazione riceve i valori originali, in modo trasparente.
Quando si utilizzano LLM per operazioni di sicurezza, incident response o qualsiasi attività che coinvolga dati reali dei clienti, si rischia di inviare PII ad API di terze parti. Questo proxy risolve il problema:
# 1. Crea il tuo file di configurazione
cp config.json.example config.json
# Modifica config.json con i tuoi domini interni, entità note, ecc.
# 2. Esegui con Docker
docker build -t llm-token-proxy .
docker run -p 8090:8080 -v ./config.json:/app/config.json llm-token-proxy
# 3. Punta la tua applicazione al proxy
export ANTHROPIC_BASE_URL=http://localhost:8090/session/my-session/
Tutto qui. Le tue chiamate all'API Anthropic passano ora attraverso il proxy con PII oscurate.

Flusso tipico: Applicazione → Token Proxy (oscuramento PII) → API LLM (solo pseudonimi) → Token Proxy (ripristino originali) → Applicazione
admin da [email protected])Gli pseudonimi sono deterministici all'interno di una sessione — lo stesso valore reale corrisponde sempre allo stesso pseudonimo.
Quando un LLM analizza log di sicurezza, il provider di hosting e la geolocalizzazione di un indirizzo IP sono importanti — un login da un IP Hetzner in Germania racconta una storia diversa da uno di un ISP residenziale negli Stati Uniti. La sostituzione ingenua con IP di intervalli di documentazione (es. 198.51.100.x) distrugge questo contesto.
Con il database MaxMind GeoLite2-ASN opzionale, il proxy sostituisce gli IP reali con un IP diverso dello stesso ASN e sottorete. Il LLM vede un IP dall'aspetto reale che risolve allo stesso provider di hosting e alla stessa geografia approssimativa — ma non è l'indirizzo reale.
10.99.99.x (nessun contesto ASN da preservare)198.51.100.x (intervallo di documentazione)L'IP donatore viene scelto deterministicamente tramite HMAC con un sale per sessione, quindi lo stesso IP reale viene sempre mappato allo stesso donatore all'interno di una sessione, ma sessioni diverse producono mappature diverse.
Il proxy viene fornito con un config.json vuoto — nessuna lista di parole predefinita o ipotesi specifiche del dominio. Il config.json.example incluso è ottimizzato per operazioni di sicurezza con Microsoft Sentinel e Entra ID (oltre 8.000 nomi di tabelle/colonne KQL, termini delle API Graph, domini di riferimento di sicurezza). Se questo corrisponde al tuo caso d'uso, copia ciò di cui hai bisogno. Se utilizzi il proxy per un dominio diverso (sanità, legale, finanza, ecc.), parti dal config vuoto e costruisci le tue liste.
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, il proxy diventa un semplice pass-throughfalse, i domini passano senza modifiche (email, IP, nomi sono ancora oscurati). Utile quando i nomi di dominio portano contesto importante per il LLM (es. distinguere outlook.com da protonmail.com) e non sono considerati sensibili.Gestisci le whitelist e attiva/disattiva l'oscuramento senza riavviare:
# Visualizza tutte le whitelist
curl http://localhost:8090/token-proxy/config/whitelist
# Aggiungi termini alla skiplist NER (riduce i falsi positivi)
curl -X POST http://localhost:8090/token-proxy/config/whitelist \
-H "Content-Type: application/json" \
-d '{"category": "ner_skiplist", "values": ["EvoSTS", "Hetzner"]}'
# Aggiungi domini alla allowlist (mai pseudonimizzare questi)
curl -X POST http://localhost:8090/token-proxy/config/whitelist \
-H "Content-Type: application/json" \
-d '{"category": "domain_allowlist", "values": ["github.com"]}'
# Disabilita l'oscuramento (modalità pass-through)
curl -X POST http://localhost:8090/token-proxy/config/status \
-H "Content-Type: application/json" \
-d '{"redaction_enabled": false}'
Categorie delle whitelist: ner_skiplist, domain_allowlist, known_persons, known_orgs, known_hostnames
Ispeziona cosa sta facendo il proxy in tempo reale:
# Elenca le sessioni attive
curl http://localhost:8090/token-proxy/sessions
# Visualizza le mappature degli pseudonimi per una sessione
curl http://localhost:8090/token-proxy/sessions/{session_id}/mappings
# Visualizza il log delle attività di oscuramento
curl http://localhost:8090/token-proxy/sessions/{session_id}/log
# Cerca nelle mappature
curl http://localhost:8090/token-proxy/sessions/{session_id}/search?q=admin
# Visualizza i payload acquisiti (ciò che il LLM ha effettivamente visto)
curl http://localhost:8090/token-proxy/sessions/{session_id}/payloads
# Utilizzo token per una sessione (token di input/output in tutte le richieste)
curl http://localhost:8090/token-proxy/sessions/{session_id}/usage
# Statistiche globali (include total_tokens in tutte le sessioni)
curl http://localhost:8090/token-proxy/stats
Il proxy registra input_tokens e output_tokens per ogni richiesta inoltrata — sia non streaming (letti dall'oggetto usage della risposta) che streaming (analizzati dagli eventi SSE message_start e message_delta). Poiché il proxy si trova tra la tua applicazione e il LLM, ottieni un unico punto di controllo per misurare il consumo da tutti i client che lo condividono, senza dover strumentare ciascuno.
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 }
L'utilizzo per richiesta è incluso anche in /token-proxy/sessions/{session_id}/log sotto usage_counts. Vengono tracciati solo i conteggi grezzi dei token — il prezzo è lasciato al chiamante.
Il proxy supporta lo streaming SSE (stream: true). Gli pseudonimi vengono ripristinati in tempo reale utilizzando un approccio con buffer di coda che gestisce gli pseudonimi suddivisi tra blocchi SSE.
Il proxy utilizza un pattern adattatore per provider. Attualmente supporta:
/v1/messages)Consulta CONTRIBUTING.md per come aggiungere il supporto per altri provider (OpenAI, Google Gemini, ecc.).
en_core_web_sm) rileva nomi di persone/organizzazioni in inglese. I nomi in altre lingue potrebbero non essere rilevati, a meno che non vengano aggiunti a known_persons/known_orgs nella configurazione.admin [at] acme.com, numeri di telefono, indirizzi fisici) non verranno rilevati. La pipeline di rilevamento è ottimizzata per dati IT/sicurezza strutturati./token-proxy/config/* e /token-proxy/sessions/* non hanno autenticazione. Il proxy è progettato per reti fidate/interne — non esporre questi endpoint a reti non fidate.# Installa le dipendenze di sviluppo
pip install -e ".[dev,ner]"
python -m spacy download en_core_web_sm
# Esegui i test
pytest
# Lint
ruff check token_proxy/ tests/
Apache 2.0 — vedi LICENSE.
| Tipo entità | Esempio interno | Esempio esterno |
|---|
[email protected] | [email protected] | |
| Dominio | domain-internal-001.com | domain-external-001.net |
| IP | 10.99.99.1 (RFC1918) | IP donatore ASN-aware (vedi sotto) |
| Persona | person_internal_001 | person_external_001 |
| Org | org_internal_001 | org_external_001 |
| Hostname | host_001 | host_001 |
| Variabile | Default | Scopo |
|---|
ANTHROPIC_API_BASE | https://api.anthropic.com | URL dell'API Anthropic upstream |
TOKEN_PROXY_CONFIG_PATH | /app/config.json | Percorso del file di configurazione |
LOG_LEVEL | info | Livello di logging |
GEOIP_ASN_DB_PATH | /app/data/GeoLite2-ASN.mmdb | Database MaxMind GeoLite2-ASN (opzionale) |