Dogfooding della nostra API a tariffa limitata


117

Panoramica:

La mia azienda ha sviluppato un'API a tariffa limitata. Il nostro obiettivo è duplice:

  • R: Crea un solido ecosistema di sviluppatori attorno al nostro prodotto.
  • B: Dimostrare la potenza della nostra API utilizzandola per guidare la nostra applicazione.

Chiarimento: perché il limite di velocità?

Valutiamo limite la nostra API, perché la vendiamo come aggiunta al nostro prodotto. L'accesso anonimo alla nostra API ha una soglia molto bassa per le chiamate API all'ora, mentre ai nostri clienti a pagamento sono consentite fino a 1000 chiamate all'ora o più.

Il problema:

La nostra API a tariffa limitata è ottima per l'ecosistema degli sviluppatori, ma per consentirci di sperimentarla non possiamo consentire che sia limitata allo stesso limite di velocità. Il front-end della nostra API è tutto JavaScript, che effettua chiamate Ajax dirette all'API.

Quindi la domanda è:

Come si protegge un'API in modo che la limitazione della velocità possa essere rimossa dove nel processo di rimozione tale limitazione della velocità non può essere facilmente falsificata?

Soluzioni esplorate (e perché non hanno funzionato)

  1. Verifica il referrer rispetto all'intestazione host. - Difettoso perché il referrer è facilmente contraffatto.

  2. Utilizzare un HMAC per creare una firma basata sulla richiesta e un segreto condiviso, quindi verificare la richiesta sul server. - Difettoso perché il segreto e l'algoritmo sarebbero facilmente determinabili esaminando il JavaScript front-end.

  3. Proxy la richiesta e firma la richiesta nel proxy - Ancora difettoso, poiché il proxy stesso espone l'API.

La domanda:

Sto cercando le menti brillanti di Stack Overflow per presentare soluzioni alternative. Come risolveresti questo problema?


13
Non puoi. Se il tuo uso dell'API che non vuoi limitare alla limitazione della velocità proviene solo da pagine web pubbliche, allora non puoi fare nulla di sicuro da quelle pagine web pubbliche perché, come sembra già sapere, ci sono nessun segreto nelle pagine web pubbliche. Quindi, quello che puoi fare nelle tue pagine web, così può farlo chiunque altro.
jfriend00

28
Sei sicuro di avere effettivamente un problema di limitazione della velocità da risolvere nell'uso del cibo per cani? Ogni utente che utilizza il tuo sito e le tue pagine web dovrebbe sembrare un utente completamente diverso dal tuo codice di limitazione della velocità. Quindi, assicurati solo che ogni pagina web rispetti le normali regole di limitazione della velocità da sola e dovresti stare bene. Supponendo che il tuo limite di velocità sia per client, un utente non avrà nulla a che fare con nessun altro utente.
jfriend00

6
Perché non prendi in considerazione una soluzione di gestione delle API che fornisce limitazione della velocità e limitazione per utente, per ruolo / autorizzazione o ambito dell'applicazione. Ad esempio, manger api wso2
MiddlewareManiac

3
Possibile duplicato della limitazione
spender

28
La tua versione sperimentale ha scoperto un problema significativo con la tua API pubblica (ovvero il limite di frequenza è troppo basso) e invece di risolverlo, stai cercando di aggirarlo. Perché dogfood se hai intenzione di ignorare i problemi che trovi?
user253751

Risposte:


93

Poiché il tuo client JavaScript accede direttamente all'API, chiunque sarà in grado di guardare ciò che sta facendo e imitarlo, incluso l'uso della stessa chiave API. Puoi provare a renderlo più difficile, ad esempio offuscando il tuo codice o mettendo vari ostacoli nel modo, ma tu e la persona che stai cercando di trattenere avete fondamentalmente lo stesso accesso. Invece di cercare di creare una differenza nei privilegi, dovrai costruire un sistema in cui è totalmente OK che il client non ufficiale utilizzi tutto l'accesso nel suo ambito, ma il sistema è organizzato in modo tale che l'uso ufficiale su tutti i client sia maggiore.

Ciò viene spesso eseguito con token di accesso per utente, anziché un token per l'intera applicazione. Il limite di ogni token dovrebbe essere sufficiente per l'uso tipico della tua API, ma restrittivo per qualcuno che cerca di abusarne. Ad esempio, 100 chiamate al minuto potrebbero essere più che sufficienti per supportare la normale navigazione, ma se voglio scartarti, non posso farlo in modo efficace con quel budget.

Ci sarà sempre una corsa agli armamenti: posso aggirare il limite creando molti account utente bot. Questo, tuttavia, è un problema abbastanza risolto se aggiungi un captcha al tuo flusso di registrazione, con un po 'di spesa per il vero umano. Quando entri in questi scenari, tutto è solo un compromesso tra comodità e restrizione. Non troverai mai qualcosa di totalmente a prova di proiettile, quindi concentrati sul renderlo abbastanza buono e aspetta che qualcuno ti sfrutti per scoprire dove erano i buchi.


8
Accettando questo come la migliore risposta. La strada che abbiamo deciso di seguire è quella di utilizzare i token JWT con una scadenza inferiore e di aumentare il limite di frequenza di tali chiamate. Codificheremo alcune informazioni aggiuntive nel token per far sapere al backend del limite di velocità più alto. Poiché questi token sono firmati in modo sicuro sul back-end, non dovrebbero esserci problemi con lo spoofing. Qualcuno potrebbe ancora usare il token, ma scadrà dopo pochi giorni e quindi sostenere qualsiasi tipo di bot sarebbe più difficile da fare.
Jason Waldrip

33

Se questo ti sta causando un problema, causerà un problema al tuo presunto ecosistema di sviluppatori (ad esempio, quando cercano di sviluppare un'interfaccia utente alternativa). Se stai davvero mangiando il tuo cibo per cani, fai in modo che l'API (e la limitazione della velocità) funzioni per la tua applicazione. Ecco alcuni suggerimenti:

  • Non limitare la velocità in base all'indirizzo IP. Piuttosto, limite di velocità da qualcosa associato all'utente, ad esempio il suo ID utente. Applica il limite di velocità nella fase di autenticazione.

  • Progetta la tua API in modo che gli utenti non debbano chiamarla continuamente (ad esempio, dare una chiamata all'elenco che restituisce molti risultati, piuttosto che una chiamata ripetuta che restituisce un elemento ogni volta)

  • Progetta la tua app web con gli stessi vincoli che ti aspetti dal tuo ecosistema di sviluppatori, ovvero assicurati di poterla progettare con tassi di limitazione ragionevoli.

  • Assicurati che il tuo back-end sia scalabile (preferibilmente orizzontalmente) in modo da non dover imporre la limitazione a livelli così bassi da causare effettivamente un problema a un'interfaccia utente.

  • Assicurati che il tuo throttling abbia la capacità di far fronte alle raffiche, oltre a limitare gli abusi a lungo termine.

  • Assicurati che il tuo throttling esegua azioni ragionevoli su misura per l'abuso che stai cercando di rimuovere. Ad esempio, prendi in considerazione la possibilità di accodare o ritardare i malintenzionati piuttosto che rifiutare la connessione. La maggior parte dei front-end Web aprirà solo quattro connessioni simultanee contemporaneamente. Se ritardi un tentativo di aprirne un quinto, verrai colpito solo nel caso in cui stiano utilizzando una CLI contemporaneamente al client web (o due client web). Se ritardi la chiamata API n-esima senza interruzioni piuttosto che fallirla, l'utente finale vedrà le cose rallentare anziché interrompersi. Se lo combini con l'accodamento delle sole chiamate API N contemporaneamente, colpirai solo le persone che stanno parallelizzando un gran numero di chiamate API, il che probabilmente non è il comportamento che desideri, ad esempio 100 chiamate API simultanee, quindi un intervallo di un'ora è normalmente lontano peggiore di 100 chiamate API sequenziali nell'arco di un'ora.

Questo non ha risposto alla tua domanda? Bene, se hai davvero bisogno di fare quello che stai chiedendo, limita la velocità nella fase di autenticazione e applica un limite di velocità diverso in base al gruppo in cui si inserisce il tuo utente. Se stai utilizzando un set di credenziali (utilizzato dai tuoi sviluppatori e dal team di QA), ottieni un limite di frequenza più elevato. Ma puoi immediatamente capire perché questo ti porterà inevitabilmente al tuo ecosistema a vedere problemi che il tuo team di sviluppo e QA non vede.


11

Acquista il tuo prodotto. Diventa un cliente pagato di te stesso.

"L'accesso anonimo alla nostra API ha una soglia molto bassa per le chiamate API all'ora, mentre ai nostri clienti a pagamento sono consentite fino a 1000 chiamate all'ora o più."

Questo aiuta anche a testare il sistema dal punto di vista del cliente.


1
La risposta ovvia. Non barare o fingere qui!
wizzwizz4

9

Sfortunatamente, non esiste una soluzione perfetta a questo.

L'approccio generale è in genere quello di fornire uno spoofablemodo per i client di identificarsi (ad esempio un identificatore, versione e chiave API - ad esempio), per i client di registrare informazioni su se stessi che possono essere utilizzate per limitare l'accesso (ad esempio il client è un server in un determinato intervallo di indirizzi IP, quindi consenti solo i chiamanti in quell'intervallo; ad esempio, il client è JavaScript, ma consegnato solo a una categoria specifica di browser, quindi consenti l'accesso solo alle richieste HTTP che specificano determinate stringhe dell'agente utente; ecc.), e quindi per utilizzare l'apprendimento automatico / pattern riconoscimento per rilevare un utilizzo anomalo che è probabile un client contraffatto e quindi per rifiutare il traffico da questi client falsificati (o confermare con i client che questi utilizzi non provengono effettivamente dal client legittimo, sostituire le loro credenziali falsificabili e quindi non consentire ulteriore traffico utilizzando il vecchio credenziali contraffatte).

Puoi rendere leggermente più difficile lo spoofing utilizzando più livelli di chiave. Ad esempio, fornisci una credenziale di più lunga durata che risiede su un server (e che può essere utilizzata solo in un insieme limitato di intervalli di indirizzi IP) per effettuare una chiamata API che registra le informazioni sul client (ad esempio, l'agente utente) e restituisce una chiave lato client più breve che viene distribuita in JavaScript per essere utilizzata sul client per richieste API lato client. Anche questo è imperfetto (uno spoofer potrebbe emettere la stessa chiamata al server per ottenere le credenziali), ma sarà più difficile se la chiave API restituita è inclusa in JavaScript o HTML offuscati (e che cambiano frequentemente) (il che renderebbe difficile per estrarre in modo affidabile dalla risposta). Ciò fornisce anche un modo per rilevare più facilmente lo spoofing; la chiave lato client è ora legata a un particolare client (es


8

Supponendo che l'app in questione debba essere aperta pubblicamente, non hai molta scelta:

Scegli un altro modo per dimostrare la potenza della tua API. Ad esempio, scrivi un'app di questo tipo e condividi la sua fonte, ma non eseguire effettivamente quel codice. Assicurati che sia ben documentato, in modo che chiunque possa distribuirlo e vederlo funzionare (soggetto a limitazione).

L'app che esegui dovrebbe essere rifattorizzata per evitare richieste API lato client ed essere più renderizzata dal server. Puoi ancora provare la tua API, ma non in modo ovvio: effettua richieste sicure all'API senza limitazioni dal lato server.

Regola la limitazione della velocità per consentire alla tua app di funzionare e investi nell'ottimizzazione delle prestazioni per gestire il carico.

E sì, in primo luogo hai l'API principale senza throttle e tienila all'interno di una rete privata. Throttle in un livello separato pubblicamente accessibile.


4

Riesci a creare un'istanza separata dell'interfaccia utente e dell'API senza limitazioni, quindi limitare l'accesso agli indirizzi IP provenienti dalla tua organizzazione?

Ad esempio, distribuisci tutto dietro il firewall aziendale e collega l'applicazione allo stesso database dell'istanza pubblica se devi condividere i dati tra le istanze.


4

Potresti provare a generare un ID di sessione univoco, associato a un determinato indirizzo IP / utente e tempo di vita limitato. Quando un utente scarica il codice JavaScript del front-end dell'applicazione, inserisci l'ID di sessione generato nel codice sorgente JavaScript. L'ID sessione verrà allegato a ogni richiesta alla tua API e il limite di frequenza verrà revocato.

L'ID non può essere semplicemente copiato per lo spoofing, perché è valido solo per un singolo indirizzo IP, utente e periodo di tempo limitato. Quindi un avversario dovrebbe chiamare la tua pagina e filtrare la chiave dalla tua fonte JavaScript o intercettare la richiesta Ajax ogni volta che un nuovo utente vuole usarla.

Un'altra opzione:

Configura un proxy per la tua applicazione e usa l'offuscamento. Le richieste Ajax al proxy utilizzano nomi diversi dalle chiamate API reali e il proxy le traduce. Quindi la tua applicazione non chiamerà la getDocumenttua vera API, ma chiamerà getFELSUFDSKJEil tuo proxy. Il proxy tradurrà questa chiamata in getDocument e la inoltrerà all'API a velocità limitata effettiva.

La tua API effettiva non limiterà le richieste del proxy.

E così che altre persone non utilizzino il tuo proxy per la propria applicazione, cambi lo schema di offuscamento ogni giorno. I nomi di chiamata offuscati possono essere generati automaticamente nel codice sorgente JavaScript e configurati nel proxy.

Un client che desidera utilizzare questo, dovrebbe anche tenere il passo con il tuo mutevole offuscamento per utilizzare il proxy. E puoi ancora usare referrer-header e simili per la registrazione, in modo da poter trovare persone che usano il tuo proxy. O catturarli quando si cambia lo schema di offuscamento.


3
  • Inserisci nella whitelist gli indirizzi IP di origine
  • Usa una VPN , autorizza i membri della VPN
  • La soluzione proxy o il componente aggiuntivo del browser che aggiunge intestazioni HTTP dovrebbero andare bene se puoi proteggere il proxy e non sei preoccupato per gli attacchi MITM che sniffano il traffico
  • Qualsiasi soluzione che coinvolga i segreti può mitigare l'impatto delle perdite ruotando i segreti su base giornaliera

Queste soluzioni non si applicano a un client Web front-end. Perfetto se l'accesso all'API era sul backend.
Jason Waldrip

@jason possono essere tutti applicati a un frontend
8472

2

Imposta più account e scegline uno a caso ad ogni richiesta o cambia quello che usi ogni ora circa. In questo modo puoi distribuire il carico sugli naccount, dandoti nlimiti fino a volte superiori.

Fai attenzione a non spegnerti accidentalmente se stai cercando di trovare altri utenti che lo fanno, se non è consentito ai clienti.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.