Bot Protection and anti-fraud API
1) Why do you need it
Bots and attackers attack the entry points of growth and money: registration, login (ATO), deposits/conclusions, promotional mechanics, catalogs of games/coefficients. Manual rules and pure rate limit are no longer enough: you need multi-level signals, real-time scoring and solution control (allow/deny/challenge/throttle) with feedback from business events (chargebacks, chargeback-ratio, KYC-files).
2) Threat taxonomy
Registration/onboarding: mass accounts, disposable e-mail/SIM banks, device farms.
ATO (Account Takeover): credential stuffing, password spraying, session hijack.
Bonus abuse: multi-booking, geo/jurisdiction arbitration, self-exclusion bypass.
Karting/payment fraud: card test, stolen wallets, refunds.
Scraping/inventory: aggressively pulling content, prices, ratios.
Low-intensity API-DoS: turtle attacks, slow-POST, mobile SDK emulations.
Webhooks/integrations: fake notifications without HMAC/mTLS, replay.
3) Protection architecture
3. 1 Layers
1. Edge (CDN/WAF/gateway): early failures (ASN/Geo/IP reputation), light challenges, limits, PoW.
2. Risk API (Risk PDP): centralized rule engine/ML; ответ — `decision`, `score`, `reason`, `ttl`.
3. App-level: domain invariants, business logic (limits, KYC, AML), asynchronous reviews.
4. Event flow: Kafka/Kinesis → feature store/model → feedback from payments/disputes.
3. 2 Solution loop
[Request] → Edge Plugins → (enrich) → Risk API (rules+ML) → Decision:
allow deny throttle challenge(type=captcha sms PoW biometry)
The solution is cached by key (for example, device × account × route) for 'ttl' seconds.
4) Signals and enrichment
Network/channel: IP/ASN, proxy/VPN/Tor, rdns, rtt/jitter, SYN-rate, TLS fingerprint (JA3/JA4), HTTP/2/3 behavior.
Device/browser: canvas/audio/WebGL FP (careful), platform/SDK, timezone/locale, resolution, fonts, WebDriver/headless indicators, mobile attestation (SafetyNet/DeviceCheck, if possible).
Behavior: input speed, mouse/touch trajectories, screen sequence, dwell-time, frequency of attempts, transitions between browser identifiers.
Content/request: form e-mail/domain, disposable providers, phone HLR/or number type, BIN card, account/IBAN in sanka registries, similarity of full name/addresses.
Account/history: account age, KYC status, retention, ARPPU, velocity by deposits/withdrawals/bonuses.
External sources: compromise lists (HIBP-like), payment risk signals (PSP), ASN reputation.
5) Solution: Rules + ML
5. 1 Rules (deterministic)
Velocity: "N registrations with/24 in 10 minutes," "M logins with one device to X accounts," "K 3DS-files in a row."
Geo/Jurisdiction: IP geo conflicts vs address/document, sudden location jumps.
Business invariants: limits of responsible payments, self-exclusion, sanctions lists.
5. 2 ML scoring (real time)
Light model (GBM/logreg) on online characteristics: 'ip _ risk', 'device _ age', 'account _ age', 'pwd _ fail _ rate', 'bin _ risk', 'velocity _', 'behavioral _'.
Separate model for ATO and separately for payments/outputs.
Segmentation by jurisdiction/tenant (per-market threshold calibration).
5. 3 Decision-making
if ip_blacklisted or bad_asn then deny else if rule_severe then challenge(hard)
else if score >= 0. 9 then deny else if 0. 7 <= score < 0. 9 then challenge(soft)
else allow
When 'challenge', store the facts of passage/failure; escalate/reduce friction dynamically.
6) Velocity and quotas (keys and windows)
Ключи: `ip`, `ip/24`, `device_id`, `account_id`, `payment_instrument`, `email_domain`, `bin`.
Windows: sliding (1m/5m/1h/24h) + individual "burst "/" sustained. "
Politicians: "hard" deny on hot routes (login/deposit), soft throttle on content.
Example of a Redis rule (pseudo):pseudo allow, retry_after = gcra_allow(key="login:ip:"+ip, rate=60/min, burst=30)
if not allow:
return 429, {"Retry-After": retry_after}
7) Challenges and testing "humanity"
CAPTCHA/turnstile: как soft-challenge; remove after high confidence in a "clean" session.
Proof-of-Work (PoW): for API/scripts - calculate a hash with a given complexity; dynamic complexity during load growth.
OTP/SMS/Email/Push: for ATO/critical operations; do not abuse (cost/UX).
WebAuthn/biometrics: high level of confidence in cash-out/changing payout details.
Device trust: bind account to a verified device; new devices → challenge.
8) Gateway/proxy integration
8. 1 Envoy: ext_authz → Risk API (pseudo)
yaml http_filters:
- name: envoy. filters. http. ext_authz typed_config:
http_service:
server_uri: { uri: http://risk-api:8080, cluster: risk, timeout: 80ms }
authorization_request:
allowed_headers:
patterns:
- exact: "x-tenant"
- exact: "x-device-id"
- exact: "user-agent"
authorization_response:
allowed_upstream_headers:
patterns: [{ exact: "x-risk-score" }, { exact: "x-risk-decision" }]
- name: envoy. filters. http. router
8. 2 NGINX/Lua: easy PoW and velocity
nginx lua_shared_dict vel 20m;
access_by_lua_block {
local ip = ngx. var. remote_addr if not gcra_allow("reg:ip:"..ip, 20, 40) then ngx. header["Retry-After"] = 30; return ngx. exit(429)
end
local pow = ngx. req. get_headers()["X-POW"]
if not verify_pow(pow, ngx. var. request_id, 18) then ngx. status = 401; ngx. say('need-pow'); return ngx. exit(401)
end
}
9) Risk API Contract
Request (enriched):json
{
"tenant":"eu-1",
"route":"POST /v1/login",
"subject":{"account_id":"a123","email":"u@d. com"},
"device":{"id":"d-xyz","fp":"...","ja3":"...","headless":false},
"network":{"ip":"203. 0. 113. 10","asn":12345,"country":"DE","rtt_ms":42},
"context":{"fail_5m":3,"pwd_reset_24h":1}
}
Answer:
json
{ "decision":"challenge", "score":0. 83, "reason":"high_velocity+new_device", "ttl_sec":900, "challenge":"captcha" }
10) Data, features and models
Feature Store (online): Redis/Scylla/KeyDB - counters/velocity/timestamps.
Batch/offline: DWH (BigQuery/S3 + Athena) for training/refits; keep marks of outflow, chargeback, manual reviews.
Models: simple for real-time (logreg/GBM); heavy (XGBoost/NN) - offline with PGMs/scaling and subsequent distillation.
Drift control: PSI, AUC/PR, calibration of thresholds by region/channel.
11) Observability and operational circuit
Metrics:- `risk_requests_total{route,decision}`
- `risk_score_bucket` (distribution)
- `waf_block_total`, `velocity_block_total`, `challenge_pass_rate`
- `ato_incidents`, `carding_detected`, `cashout_denied`
- business metrics: 'chargeback _ rate', 'bonus _ abuse _ rate', 'false _ positive _ rate'
- Logs (edited): 'decision', 'score', key signals, 'trace _ id', no PII/secrets.
- A/B and Shadow: a new policy in shadow mode (we log decisions), then canary (1-5%), auto-rollback via SLO/FP.
- Playbooks: escalation, temporary tightening, rollback, "virtual patches."
12) Privacy and compliance
Minimize PII; hash stable identifiers (for example, email SHA-256 with salt).
Respect regional jurisdiction (data localization, consent).
Transparent explanations of decisions for manual reviews; keep only what you need and with TTL.
13) Specifics of iGaming/Finance
Registration: disposable e-mail/VoIP filters, velocity by/24, device farm → challenge/deny.
Login/ATO: new devices/geo-jumps → OTP/WebAuthn; password spraying → throttle/deny.
Bonuses: limits on the "path to laundering" (depozit→bonus→minimalnyy oborot→vyvod), graph analysis of affiliation (addresses/devices/cards).
Payments/withdrawals: BIN risk, country-mismatch, PSP signals; cashout to the new instrument → a high threshold and KYC checkup.
Webhooks PSP/KYC: HMAC + mTLS, narrow IP-allow-list, anti-replay ('X-Timestamp', window ± 5 minutes).
14) Antipatterns
One universal captcha "everywhere and always" → a high FP/conversion drop.
Only rate limit without behavioral/device signals.
Storage of "raw" prints and PII is unlimited.
No shadow run and canary for new policies.
Full confidence in external "reputational" labels without own validation.
Make decisions on the client (JS/Mobile SDK) without server validation.
15) Rule Examples and Pseudocode
15. 1 Composite rule (real-time)
pseudo score = 0 if ip_asn in bad_asn_list then score += 0. 5 if device_age < 1d and route in {login, withdraw} then score += 0. 3 if velocity("login:account", 5m) > 10 then score += 0. 3 if geovelocity(last_login_loc, current_loc) > 800km/h then score += 0. 2 decision = score>=0. 9? "deny": score>=0. 7? "challenge": "allow"
15. 2 Relationship graph (multi-account)
edge(accountA, deviceX)
edge(accountB, deviceX)
edge(accountB, cardY)
edge(accountC, cardY)
Threshold by common nodes → investigation/deny bonus
16) Prod Readiness Checklist
- Multi-level architecture: Edge → Risk API → App, event flow.
- Signals: network, device, behavior, content, payment; PII minimization.
- Velocity/GCRA on ip/device/account/payment keys, sliding windows.
- Solutions: allow/deny/challenge/throttle; Solution cache with TTL a repository of challenge facts.
- Challenges: captcha/PoW/OTP/WebAuthn; dynamic complexity.
- Risk API: SLA <100ms, cache, degraded to "minimum safe" mode.
- Observability: risk, FP/FN, dashboards, alerts; business metrics (chargeback/bonus-abuse).
- Shadow → canary → enforce; escalation and rollback playbooks.
- Webhooks PSP/KYC: HMAC + mTLS + anti-replay + allow-list.
- Regional requirements and TTL on sensitive data.
17) TL; DR
Build layered protection: early edge filters and challenges, centralized Risk API with + ML rules, and event flow for feedback. Use velocity limits, network/device/behavior signals, dynamic challenges (captcha/PoW/OTP/WebAuthn). Make decisions allow/deny/challenge/throttle, measure FP/FN and business effect, roll through shadow/canary. For payment/bonus paths - separate tightened profiles and a link with KYC/AML.