TRACIO analizza l'indirizzo IP di ogni visitatore lato server. Segnala VPN, proxy, nodi di uscita Tor e origini datacenter, e risolve la geolocalizzazione a livello di città e l'ASN. Tutta l'analisi viene eseguita lato server senza dipendenze lato client.
L'IP intelligence raggiunge la propria applicazione attraverso il payload del webhook: l'oggetto
network (booleani VPN/proxy/Tor/datacenter più il tipo di connessione) e l'oggetto
geo (paese, città, coordinate, fuso orario, ISP) sono consegnati su ogni
webhook. Vedi Webhooks per la struttura completa del payload e la verifica
della firma.
La classificazione di VPN, proxy, Tor e datacenter è risolta a partire dall'IP di connessione
usando database commerciali di IP intelligence (IP2Location per il tipo VPN/proxy/Tor,
MaxMind per la geolocalizzazione e l'ASN). Ciascuna è esposta come un singolo booleano sull'oggetto
network del webhook — non esiste un dettaglio per metodo o un punteggio di confidenza nel
payload pubblico.
| Flag | Campo | Significato |
|---|---|---|
| VPN | network.vpn | L'IP appartiene a un provider VPN noto |
| Proxy | network.proxy | L'IP è un proxy datacenter o residenziale |
| Tor | network.tor | L'IP è un nodo di uscita Tor noto |
| Datacenter | network.datacenter | L'IP appartiene a un provider cloud/hosting |
{ "network": { "vpn": true, "proxy": false, "tor": false, "datacenter": false, "connectionType": "residential" }}// `payload` è il corpo di consegna del webhook (/docs/webhooks)if (payload.network.vpn) { // il visitatore si connette tramite una VPN}I proxy datacenter e residenziali sono entrambi esposti come network.proxy; l'origine datacenter
è inoltre riportata come network.datacenter. La classificazione proviene dal
database proxy di IP2Location, che copre i principali provider cloud/hosting (AWS,
Google Cloud, Azure, Oracle Cloud, Alibaba Cloud, DigitalOcean, Hetzner, OVH,
Linode/Akamai, Vultr e altri).
{ "network": { "vpn": false, "proxy": true, "tor": false, "datacenter": true, "connectionType": "datacenter" }}Una corrispondenza con un nodo di uscita Tor sull'IP di connessione è esposta come network.tor. Separatamente,
il Tor Browser stesso viene rilevato lato client tramite la sua configurazione anti-fingerprinting
(resistenza canvas/WebGL, fuso orario UTC, dimensione schermo arrotondata) — vedi
Smart Signals.
La geolocalizzazione a livello di città e l'ASN sono risolti lato server a partire dall'IP di connessione
(MaxMind) e consegnati sull'oggetto geo del webhook.
| Campo | Tipo | Descrizione |
|---|---|---|
geo.country | string | Codice paese ISO 3166-1 alpha-2 |
geo.city | string | Nome della città |
geo.lat | number | Latitudine approssimativa |
geo.lon | number | Longitudine approssimativa |
geo.timezone | string | Identificatore di fuso orario IANA |
geo.isp | string | Nome dell'Internet service provider |
{ "geo": { "country": "CZ", "city": "Prague", "lat": 50.05, "lon": 14.4, "timezone": "Europe/Prague", "isp": "Comcast Cable" }}La corrispondenza con blocklist IP e il tracciamento della velocity (attività cross-IP / cross-paese)
non fanno parte del contratto pubblico attuale. Né il payload del webhook né
la dashboard espongono categorie di blocklist o intervalli di velocity. La superficie del webhook
per il rischio di rete è limitata ai flag booleani network e al
tipo di connessione; li usi insieme ai campi decision e bot (vedi
Smart Signals) per le decisioni di rischio.
Questo legge direttamente l'oggetto network del payload del webhook. Vedi
Webhooks per il payload completo e la verifica della firma.
// `payload` è il corpo di consegna del webhook (/docs/webhooks)function assessIPRisk(payload: WebhookPayload) { const { vpn, proxy, tor, datacenter } = payload.network
const risks: string[] = [] let riskLevel = "low"
if (tor) { risks.push("Tor exit node") riskLevel = "critical" }
if (vpn) { risks.push("VPN detected") riskLevel = riskLevel === "low" ? "medium" : riskLevel }
if (proxy) { risks.push("Proxy detected") riskLevel = riskLevel === "low" ? "medium" : riskLevel }
if (datacenter) { risks.push("Datacenter IP") riskLevel = riskLevel === "low" ? "medium" : riskLevel }
return { riskLevel, risks }}