Satelit Shield, de la script la server.
Baza este https://api.satelit.md/shield/v1. Pagina folosește cheia publică a site-ului; serverul tău trimite secretul în Authorization: Bearer shs_….
-
Adaugă site-ul și ia cheile
În panou adaugi site-ul și domeniile lui. Primești cheia site-ului, publică (
shp_și 24 de caractere), și secretul (shs_și 40), pe care îl vezi o singură dată. -
Pune senzorul pe pagini
Direct sau prin proxy first-party. Un site nou pornește cu toate regulile în observare (
shadow).<!-- in every page, direct --> <script src="https://api.satelit.md/shield/v1/sensor.js" data-site="shp_XXXXXXXXXXXXXXXXXXXXXXXX" async></script># Caddyfile: /_sh/* goes to Shield, with your secret and the visitor's address example.md { handle_path /_sh/* { rewrite * /shield/v1{uri} reverse_proxy https://api.satelit.md { header_up Host {upstream_hostport} header_up X-Shield-Secret {env.SHIELD_SECRET} header_up X-Shield-Client-IP {client_ip} header_up -Cookie header_up -Authorization } } # ... the rest of your site } # in every page: # <script src="/_sh/sensor.js" data-site="shp_XXXXXXXXXXXXXXXXXXXXXXXX" data-base="/_sh" async></script># nginx: /_sh/ goes to Shield, with your secret and the visitor's address location /_sh/ { proxy_pass https://api.satelit.md/shield/v1/; proxy_ssl_server_name on; proxy_set_header Host api.satelit.md; proxy_set_header X-Shield-Secret "shs_..."; # keep this file out of your repository proxy_set_header X-Shield-Client-IP $remote_addr; # behind Cloudflare: $http_cf_connecting_ip proxy_set_header Cookie ""; proxy_set_header Authorization ""; } # in every page: # <script src="/_sh/sensor.js" data-site="shp_XXXXXXXXXXXXXXXXXXXXXXXX" data-base="/_sh" async></script> -
Citește evenimentele, apoi pornește protecția
În panou vezi ce ar fi oprit fiecare regulă. Treci pe
enforceregulile în care ai încredere.
Atributele scriptului
| Atribut | Ce face |
|---|---|
data-site | Obligatoriu. Cheia publică a site-ului. |
data-base | Unde trimite senzorul rapoartele. Implicit: dosarul din care s-a încărcat scriptul; prin proxy first-party, /_sh. |
data-overlay="0" | 0: senzorul nu desenează niciodată verificarea în pagină; serverul tău servește pagina de verificare. |
<!-- in every page, direct -->
<script src="https://api.satelit.md/shield/v1/sensor.js"
data-site="shp_XXXXXXXXXXXXXXXXXXXXXXXX" async></script>Proxy first-party
Serverul tău trimite /_sh/* la https://api.satelit.md/shield/v1/*, adaugă X-Shield-Secret și X-Shield-Client-IP (și, dacă vrei, X-Shield-Client-Country) și lasă neschimbate User-Agent, Accept-Language, Sec-Fetch-* și Sec-CH-UA*. Adresa clientului este crezută doar împreună cu secretul corect. Cookie-urile vizitatorilor nu trebuie să plece spre Shield.
# Caddyfile: /_sh/* goes to Shield, with your secret and the visitor's address
example.md {
handle_path /_sh/* {
rewrite * /shield/v1{uri}
reverse_proxy https://api.satelit.md {
header_up Host {upstream_hostport}
header_up X-Shield-Secret {env.SHIELD_SECRET}
header_up X-Shield-Client-IP {client_ip}
header_up -Cookie
header_up -Authorization
}
}
# ... the rest of your site
}
# in every page:
# <script src="/_sh/sensor.js" data-site="shp_XXXXXXXXXXXXXXXXXXXXXXXX" data-base="/_sh" async></script> # nginx: /_sh/ goes to Shield, with your secret and the visitor's address
location /_sh/ {
proxy_pass https://api.satelit.md/shield/v1/;
proxy_ssl_server_name on;
proxy_set_header Host api.satelit.md;
proxy_set_header X-Shield-Secret "shs_..."; # keep this file out of your repository
proxy_set_header X-Shield-Client-IP $remote_addr; # behind Cloudflare: $http_cf_connecting_ip
proxy_set_header Cookie "";
proxy_set_header Authorization "";
}
# in every page:
# <script src="/_sh/sensor.js" data-site="shp_XXXXXXXXXXXXXXXXXXXXXXXX" data-base="/_sh" async></script> API-ul JavaScript
SatelitShield.ready(fn):fn({a, t, explain})după primul raport al paginii.a:''nimic,'g'verificare,'b'oprit.SatelitShield.token(fn):fn(token)cu un token de verdict nou, pentru un formular sau un apel API. Îl verifici pe server.SatelitShield.version: versiunea senzorului.- Evenimentul
satelit-shieldpedocument, cu acelașidetailcaready.
// after the page's first report
SatelitShield.ready(function (r) {
// r.a: "" nothing, "g" a check, "b" blocked; r.t: a verdict token
});
document.addEventListener("satelit-shield", function (e) {
console.log(e.detail.a, e.detail.t);
});
// a fresh token goes with the form, in a hidden field
form.addEventListener("submit", function (e) {
e.preventDefault();
SatelitShield.token(function (token) {
form.elements.shield_token.value = token;
form.submit();
});
});Pagina de verificare și pagina de oprire
Modul paginii vine din atributul data-shield al elementului html. Fără atribut: o pagină obișnuită. check: pagina ta de verificare, cu statusul 429; senzorul o rezolvă, păstrează permisul și reîncarcă aceeași adresă. ban: pagina cu statusul 403; senzorul doar o traduce.
<!doctype html>
<html lang="ro" data-shield="check">
<head>
<meta charset="utf-8">
<meta content="noindex" name="robots">
<script src="/_sh/sensor.js" data-site="shp_XXXXXXXXXXXXXXXXXXXXXXXX" data-base="/_sh" async></script>
</head>
<body><p>Se verifică browserul.</p></body>
</html>Cookie-urile
__shpPermisul după o verificare rezolvată:p1.{exp}.{token}.{sig}.__shs1: browserul a rulat senzorul (400 de zile), ca un cititor care revine să nu fie socotit fără dovadă.
Amândouă sunt first-party, pe domeniul tău: SameSite=Lax, Secure pe https, calea /.
Permisul, verificat la tine
Un permis se verifică pe serverul tău, fără niciun apel către Shield.
- Cheia permisului:
HMAC-SHA256(key = sha256_hex(secret), "satelit-shield-pass-v1"), în hex. O calculezi o dată. sigsunt primele 22 de caractere dinbase64url(HMAC-SHA256(cheia permisului, "p1|{exp}|{token}|{client key}|{User-Agent}"));expîn secunde unix,token16 caractere hex.- Permisul e valabil cât
expnu a trecut și semnătura se potrivește cu cheia clientului și User-Agent-ul acestei cereri: un permis copiat pe altă adresă sau în alt browser nu deschide nimic. - Durata: 12 ore; 2 ore pentru clienții cu risc (Tor, o rețea de hosting, o flotă, o decizie dură în ultimele 7 zile). Un permis deschide o verificare, niciodată o oprire.
// Satelit Shield: check a pass (the __shp cookie) on your own server, with no call to Shield. Node 18+.
// A pass is p1.{exp}.{token}.{sig}; sig is the first 22 characters of
// base64url(HMAC-SHA256(pass key, "p1|{exp}|{token}|{client key}|{User-Agent}")).
import { createHash, createHmac, timingSafeEqual } from "node:crypto";
// The pass key: HMAC-SHA256 with the key sha256_hex(secret) over "satelit-shield-pass-v1", in hex.
export function passKey(secret) {
const key = createHash("sha256").update(secret).digest("hex");
return createHmac("sha256", key).update("satelit-shield-pass-v1").digest("hex");
}
// The client key: an IPv4 address as it is, an IPv6 address as its /64 (the first four groups and "::").
export function clientKey(ip) {
const v4 = /^(?:::ffff:)?(\d{1,3}(?:\.\d{1,3}){3})$/i.exec(ip);
if (v4) return v4[1];
const [head, tail = ""] = ip.toLowerCase().split("%")[0].split("::");
const a = head ? head.split(":") : [];
const b = tail ? tail.split(":") : [];
const groups = [...a, ...Array(Math.max(0, 8 - a.length - b.length)).fill("0"), ...b];
return groups.slice(0, 4).map((g) => parseInt(g, 16).toString(16)).join(":") + "::";
}
// True when the pass has not expired and was signed for this address and this browser.
export function passValid(pass, secret, ip, userAgent, now = Date.now() / 1000) {
const m = /^p1\.(\d+)\.([0-9a-f]{16})\.([A-Za-z0-9_-]{22})$/.exec(pass ?? "");
if (!m || Number(m[1]) <= now) return false;
const message = `p1|${m[1]}|${m[2]}|${clientKey(ip)}|${userAgent}`;
const sig = createHmac("sha256", passKey(secret)).update(message).digest("base64url").slice(0, 22);
return timingSafeEqual(Buffer.from(sig), Buffer.from(m[3]));
}
"""Satelit Shield: check a pass (the __shp cookie) on your own server, with no call to Shield. Python 3.8+.
A pass is p1.{exp}.{token}.{sig}; sig is the first 22 characters of
base64url(HMAC-SHA256(pass key, "p1|{exp}|{token}|{client key}|{User-Agent}")).
"""
import base64
import hashlib
import hmac
import ipaddress
import re
import time
PASS = re.compile(r"p1\.(\d+)\.([0-9a-f]{16})\.([A-Za-z0-9_-]{22})")
def pass_key(secret):
"""HMAC-SHA256 with the key sha256_hex(secret) over "satelit-shield-pass-v1", in hex."""
key = hashlib.sha256(secret.encode()).hexdigest().encode()
return hmac.new(key, b"satelit-shield-pass-v1", hashlib.sha256).hexdigest()
def client_key(ip):
"""An IPv4 address as it is, an IPv6 address as its /64 (the first four groups and "::")."""
a = ipaddress.ip_address(ip.split("%")[0])
if a.version == 6 and a.ipv4_mapped:
a = a.ipv4_mapped
if a.version == 4:
return str(a)
return ":".join(format(int(g, 16), "x") for g in a.exploded.split(":")[:4]) + "::"
def pass_valid(value, secret, ip, user_agent, now=None):
"""True when the pass has not expired and was signed for this address and this browser."""
m = PASS.fullmatch(value or "")
if not m or int(m[1]) <= (time.time() if now is None else now):
return False
message = f"p1|{m[1]}|{m[2]}|{client_key(ip)}|{user_agent}".encode()
mac = hmac.new(pass_key(secret).encode(), message, hashlib.sha256).digest()
sig = base64.urlsafe_b64encode(mac).decode().rstrip("=")[:22]
return hmac.compare_digest(sig, m[3])
Cheia clientului
Adresa IPv4 ca atare; la IPv6, rețeaua /64, scrisă ca primele patru grupuri urmate de :: (2a01:4f8:221:1f15::). Opririle, verificările, permisele și contoarele sunt pe cheia clientului.
Apelurile de server
Toate cer Authorization: Bearer shs_… și se fac doar de pe server.
POST /verify
Verifică un token de verdict. Un token trăiește 300 de secunde și se verifică o singură dată; altfel success e false, cu error: used, expired, invalid sau other_ip. Cu ip, un token de la altă cheie de client e refuzat. score: de la 0, un om, la 100, un bot sigur.
curl https://api.satelit.md/shield/v1/verify \
-H "Authorization: Bearer $SHIELD_SECRET" \
-H "Content-Type: application/json" \
-d '{
"token": "<the verdict token>",
"ip": "203.0.113.9",
"ua": "Mozilla/5.0 ..."
}'{
"ok": true,
"success": true,
"score": 3,
"verdict": "human",
"action": "allow",
"rules": [],
"signals": {
"hard": [],
"soft": [],
"st": []
},
"crawler": null,
"issued_at": "2026-11-05T21:00:00Z",
"age_s": 4
}POST /assess
O cerere, sincron. challenge: servește pagina de verificare (429); block: 403. O decizie în observare răspunde allow, cu would. Cererea se numără la reguli exact ca o linie /ingest.
curl https://api.satelit.md/shield/v1/assess \
-H "Authorization: Bearer $SHIELD_SECRET" \
-H "Content-Type: application/json" \
-d '{
"ip": "203.0.113.9",
"ua": "Mozilla/5.0 ...",
"method": "GET",
"path": "/ro/catalog/",
"host": "example.md",
"kind": "html",
"headers": {
"sec-fetch-site": "none",
"sec-ch-ua": "...",
"sec-ch-ua-mobile": "?0",
"sec-ch-ua-platform": "\"Windows\"",
"accept-language": "ro-RO,ro;q=0.9",
"referer": ""
},
"pass": "",
"seen": true
}'{
"action": "allow",
"rule": "",
"mode": "",
"would": "",
"crawler": null,
"key": "203.0.113.9",
"until": null
}POST /ingest
Loturi de cel mult 500 de linii, fără să aștepți răspunsul. k: html o pagină, api un apel JSON, asset un fișier. pass: 0 lipsă, 1 valabil, 2 prezent dar invalid. seen: cookie-ul __shs. g: 1 când răspunsul a fost pagina de verificare.
curl https://api.satelit.md/shield/v1/ingest \
-H "Authorization: Bearer $SHIELD_SECRET" \
-H "Content-Type: application/json" \
-d '{
"lines": [
{
"t": 1762369200000,
"ip": "203.0.113.9",
"ua": "Mozilla/5.0 ...",
"m": "GET",
"p": "/ro/catalog/",
"s": 200,
"k": "html",
"h": {
"sfs": "none",
"chua": "...",
"chm": "?0",
"chp": "\"Windows\"",
"al": "ro-RO",
"ref": ""
},
"pass": 1,
"seen": 1,
"g": 0
}
]
}'{
"ok": true,
"n": 1,
"decided": 0
}GET /decisions?since=0
since=0, sau fără since, dă toată lista activă; cu cursorul primit, doar schimbările. a: b oprire (403), g verificare (429 fără un permis valabil), - ridicată. Deciziile în observare nu apar aici. Citește lista o dată la 15–30 de secunde și ține-o în memorie.
curl "https://api.satelit.md/shield/v1/decisions?since=0" \
-H "Authorization: Bearer $SHIELD_SECRET"{
"cursor": "1234",
"full": true,
"items": [
{
"key": "203.0.113.9",
"a": "b",
"rule": "automation",
"until": "2026-11-06T21:00:00Z"
},
{
"key": "2a01:4f8:1:2::",
"a": "g",
"rule": "no-proof",
"until": "2026-11-06T21:00:00Z"
},
{
"key": "198.51.100.4",
"a": "-",
"rule": "",
"until": null
}
]
}GET /config
Setările site-ului: modurile, pragurile, calea-capcană, durata permisului, planul și consumul lunii.
curl "https://api.satelit.md/shield/v1/config" \
-H "Authorization: Bearer $SHIELD_SECRET"{
"site": "shp_XXXXXXXXXXXXXXXXXXXXXXXX",
"name": "example.md",
"modes": {
"automation": "enforce",
"no-proof": "shadow"
},
"thresholds": {},
"trap": "/_sh/t/9f3k2",
"overlay": true,
"pass_life": 43200,
"plan": "shield_pro",
"quota": {
"month": "2026-11",
"used": 1234,
"limit": 2500000
}
}POST /trust
O adresă protejată pentru un număr de zile: regulile dure arată doar verificarea. Pentru un membru care plătește sau pentru un birou.
curl https://api.satelit.md/shield/v1/trust \
-H "Authorization: Bearer $SHIELD_SECRET" \
-H "Content-Type: application/json" \
-d '{
"ip": "203.0.113.9",
"days": 30
}'{
"ok": true,
"key": "203.0.113.9",
"until": "2026-12-05T21:00:00+00:00"
}GET /events?limit=50 · GET /stats?days=7
Aceleași rânduri ca în panou: evenimentele, cu filtre după regulă și acțiune, și cifrele pe zile.
curl "https://api.satelit.md/shield/v1/events?limit=50" \
-H "Authorization: Bearer $SHIELD_SECRET"{
"items": [
{
"id": 81,
"at": "2026-11-05T21:04:00Z",
"key": "198.51.100.7",
"rule": "automation",
"action": "ban",
"mode": "enforce",
"ua": "Mozilla/5.0 ... HeadlessChrome/141.0.0.0 ...",
"evidence": {
"hard": [
"wd"
]
}
}
]
}Verifică tokenul la formulare
La un vot, un comentariu sau o înregistrare, pagina cere un token cu SatelitShield.token() și îl trimite cu formularul. Serverul tău îl verifică o singură dată, în 300 de secunde.
curl https://api.satelit.md/shield/v1/verify \
-H "Authorization: Bearer $SHIELD_SECRET" \
-H "Content-Type: application/json" \
-d '{
"token": "<the token from the form>",
"ip": "203.0.113.9"
}' // Node 18+: the token came with the form, ip is the visitor's address
async function fromPerson(token, ip) {
const res = await fetch("https://api.satelit.md/shield/v1/verify", {
method: "POST",
headers: { Authorization: `Bearer ${process.env.SHIELD_SECRET}`, "Content-Type": "application/json" },
body: JSON.stringify({ token, ip }),
});
const v = await res.json();
return v.success === true && v.action !== "block";
} import json, os, urllib.request
def from_person(token, ip):
req = urllib.request.Request(
"https://api.satelit.md/shield/v1/verify",
data=json.dumps({"token": token, "ip": ip}).encode(),
headers={"Authorization": f"Bearer {os.environ['SHIELD_SECRET']}", "Content-Type": "application/json"},
)
with urllib.request.urlopen(req, timeout=5) as res:
v = json.load(res)
return v.get("success") is True and v.get("action") != "block" <?php
function from_person(string $token, string $ip): bool {
$ch = curl_init("https://api.satelit.md/shield/v1/verify");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_TIMEOUT => 5,
CURLOPT_HTTPHEADER => ["Authorization: Bearer " . getenv("SHIELD_SECRET"), "Content-Type: application/json"],
CURLOPT_POSTFIELDS => json_encode(["token" => $token, "ip" => $ip]),
]);
$v = json_decode(curl_exec($ch), true);
curl_close($ch);
return ($v["success"] ?? false) === true && ($v["action"] ?? "") !== "block";
} Un middleware în Node
Deciziile în memorie, cererile la /ingest în loturi, permisul verificat local. Rulează așa cum este, cu SHIELD_SECRET și SHIELD_SITE în mediu.
Opțional, pentru tot site-ul. Un middleware ține deciziile în memorie, le citește din /decisions o dată la 15–30 de secunde și trimite cererile în loturi la /ingest. Nicio cerere a unui vizitator nu așteaptă rețeaua.
// Satelit Shield in a Node server: Express or any (req, res, next) stack. Node 18+, no packages.
// The decisions stay in memory and are read again every 20 s, so a visitor's request never waits for the network.
// Every request is sent to /ingest in batches. /_sh/ (the sensor) is served by the proxy in front, step 1.
import { clientKey, passValid } from "./shield-pass.mjs";
const API = process.env.SHIELD_API || "https://api.satelit.md/shield/v1";
const SECRET = process.env.SHIELD_SECRET; // shs_..., never in a page
const SITE = process.env.SHIELD_SITE; // shp_..., the public site key
const HEADERS = { Authorization: `Bearer ${SECRET}`, "Content-Type": "application/json" };
const decisions = new Map(); // client key -> { a: "b" | "g", rule, until }
const lines = [];
let cursor = "0";
export async function poll() {
const res = await fetch(`${API}/decisions?since=${cursor}`, { headers: HEADERS });
if (!res.ok) return;
const body = await res.json();
if (body.full) decisions.clear();
for (const d of body.items) {
if (d.a === "-") decisions.delete(d.key);
else decisions.set(d.key, d);
}
cursor = body.cursor;
}
export async function flush() {
while (lines.length) {
const batch = lines.splice(0, 500);
await fetch(`${API}/ingest`, { method: "POST", headers: HEADERS, body: JSON.stringify({ lines: batch }) }).catch(() => {});
}
}
export function start() {
const quiet = (job) => () => job().catch(() => {});
quiet(poll)();
setInterval(quiet(poll), 20_000).unref();
setInterval(quiet(flush), 5_000).unref();
}
const cookie = (req, name) => new RegExp(`(?:^|;\\s*)${name}=([^;]*)`).exec(req.headers.cookie ?? "")?.[1] ?? "";
const page = (mode, text) => `<!doctype html><html data-shield="${mode}"><head><meta charset="utf-8">`
+ `<meta content="noindex" name="robots"><meta name="viewport" content="width=device-width">`
+ `<script src="/_sh/sensor.js" data-site="${SITE}" data-base="/_sh" async></script></head><body><p>${text}</p></body></html>`;
export function shield(req, res, next) {
const ip = req.ip ?? req.socket.remoteAddress; // behind a proxy: Express's "trust proxy" gives the visitor's address
const ua = req.headers["user-agent"] ?? "";
const path = (req.originalUrl ?? req.url).split("?")[0];
const shp = cookie(req, "__shp");
const pass = !shp ? 0 : passValid(shp, SECRET, ip, ua) ? 1 : 2;
const d = decisions.get(clientKey(ip));
const on = d && (!d.until || Date.parse(d.until) > Date.now()) ? d.a : "";
// a ban is a 403; a check is a 429 unless the browser holds a valid pass (a pass never opens a ban)
const gate = on === "b" ? 403 : on === "g" && pass !== 1 ? 429 : 0;
res.on("finish", () => {
const type = String(res.getHeader("content-type") ?? "");
const kind = /\.(css|js|mjs|png|jpe?g|gif|svg|webp|avif|ico|woff2?)$/i.test(path) ? "asset" : /json/.test(type) ? "api" : "html";
const h = (name) => req.headers[name] ?? "";
lines.push({
t: Date.now(), ip, ua, m: req.method, p: path, s: res.statusCode, k: kind,
h: { sfs: h("sec-fetch-site"), chua: h("sec-ch-ua"), chm: h("sec-ch-ua-mobile"), chp: h("sec-ch-ua-platform"), al: h("accept-language"), ref: h("referer") },
pass, seen: cookie(req, "__shs") === "1" ? 1 : 0, g: gate === 429 ? 1 : 0,
});
});
if (!gate) return next();
res.statusCode = gate;
res.setHeader("Content-Type", "text/html; charset=utf-8");
res.setHeader("Cache-Control", "no-store");
res.end(gate === 429 ? page("check", "Checking your browser.") : page("ban", "Access blocked."));
}
Erori
Un apel greșit răspunde cu error.code și error.message.
| Cod | Când |
|---|---|
unauthorized | Secretul lipsește sau este greșit. |
forbidden_origin | Pagina nu este pe un domeniu al site-ului (sau un subdomeniu). |
invalid | Cererea nu are forma din această pagină. |
quota | Verificările lunii s-au terminat. Senzorul nu strică pagina: răspunde ca și cum nu ar fi nimic de făcut. |
busy | Shield este ocupat. Încearcă din nou peste câteva secunde. |
not_found | Site-ul sau resursa nu există. |
{
"error": {
"code": "unauthorized",
"message": "The secret is missing or wrong"
}
}Regulile
Fiecare regulă are modul ei: off, shadow sau enforce.
Regulile dure opresc o adresă neprotejată. Cele slabe arată doar verificarea. O regulă care trece de 50 de opriri pe oră, sau un site care trece de 200, revine singură la observare, iar tu primești un eveniment.
-
automationWebDriver, ChromeDriver, Selenium, PhantomJS, Nightmare, Playwright, Puppeteer, Cypress, TestCafe, HeadlessChrome.
-
stealthAutomatizare peticită: Function.toString înlocuit, fereastră din iframe detașat, webdriver redefinit, Chromium deghizat în Chrome, un worker care spune HeadlessChrome.
-
antidetectAmprentă falsificată: motor JS mai vechi decât browserul declarat, zgomot pe canvas, ecran diferit de CSS, fus orar, limbă, fonturi de sistem lipsă, worker sau Client Hints în dezacord.
-
fake-crawlerUn nume de crawler infirmat de două surse independente: lista IP oficială și DNS-ul invers.
-
robotsUn bot declarat care cere căi interzise grupului său din robots.txt.
-
trapCalea-capcană ascunsă a site-ului, interzisă în robots.txt.
-
challenge-ignoredPagina de verificare servită de 6 sau mai multe ori aceleiași adrese, fără răspuns.
-
browser-softDouă sau mai multe semne slabe: fără pluginuri pe Chrome desktop, fără window.chrome, limbi goale, WebGL software, protocolul DevTools.
-
no-proof12 sau mai multe pagini în 10 minute, fără raport al senzorului și fără cookie-ul __shs.
-
rate60 sau mai multe pagini pe minut.
-
walk40 sau mai multe pagini diferite în 10 minute.
-
stale-browserChrome desktop cu 8 sau mai multe versiuni în urmă, fără permis și fără __shs.
-
ua-claimChrome 101+ cu numărul complet de build (Chrome real scrie N.0.0.0) sau fără Sec-Fetch-Site pe Chrome 80+.
-
client-hintsAntetele Sec-CH-UA contrazic User-Agent-ul: mobil, platformă, versiune, sau lipsesc pe Chrome 90+.
-
datacenterUn User-Agent de browser dintr-o rețea de hosting sau cloud (ASN), fără permis.
- Nu sunt judecați niciodată
- Crawlerele verificate și lista ta de permise.
- Doar verificare, niciodată oprire
- Ieșirile Tor, adresele comune (3 sau mai multe browsere reale pe aceeași adresă în 24 de ore) și adresele în care ai încredere.
Ce păstrează Shield
- Doar ID-uri de verificări. Senzorul trimite ID-urile verificărilor, numărul de interacțiuni (fără poziții sau taste) și prima limbă a browserului. Niciun hash de amprentă.
- Cookie-uri doar pe domeniul tău.
__shp, permisul după o verificare, și__shs, semnul că browserul a rulat senzorul. Satelit nu pune niciun cookie al său. - Păstrare scurtă. Cheia clientului (adresa sau rețeaua /64), User-Agent-ul, regula și dovada ei: 30 de zile. Contoarele pe oră: 90 de zile.
- Secretul rămâne pe server. Cheia site-ului e publică. Secretul îl vezi o singură dată, iar Satelit păstrează doar hash-ul lui.