Dogfooding nossa própria API de taxa limitada

117

Visão geral:

Minha empresa desenvolveu uma API de taxa limitada. Nosso objetivo é duplo:

  • R: Crie um ecossistema de desenvolvedor forte em torno de nosso produto.
  • B: Demonstre o poder de nossa API usando-a para conduzir nosso próprio aplicativo.

Esclarecimento: Por que limite de taxa?

Limitamos nossa taxa de API, porque a vendemos como um complemento ao nosso produto. O acesso anônimo à nossa API tem um limite muito baixo para chamadas de API por hora, enquanto nossos clientes pagos têm permissão para mais de 1000 chamadas por hora ou mais.

O problema:

Nossa API de taxa limitada é ótima para o ecossistema do desenvolvedor, mas para que possamos aplicá-la em dogfood, não podemos permitir que seja restrita à mesma limitação de taxa. O front-end de nossa API é todo em JavaScript, fazendo chamadas Ajax diretas para a API.

Portanto, a questão é:

Como você protege uma API de modo que a limitação de taxa possa ser removida onde, no processo, a remoção dessa limitação de taxa não pode ser facilmente falsificada?

Soluções exploradas (e por que não funcionaram)

  1. Verifique o referenciador em relação ao cabeçalho do host. - Falha porque o referenciador é facilmente falsificado.

  2. Use um HMAC para criar uma assinatura com base na solicitação e um segredo compartilhado e, em seguida, verifique a solicitação no servidor. - Falha porque o segredo e o algoritmo seriam facilmente determinados examinando o JavaScript de front end.

  3. Proceda à solicitação e assine a solicitação no proxy - Ainda falho, pois o próprio proxy expõe a API.

A questão:

Estou pensando nas mentes brilhantes do Stack Overflow para apresentar soluções alternativas. Como resolveria este problema?

Jason Waldrip
fonte
13
Você não pode. Se o seu próprio uso da API que você não deseja restringir à limitação de taxa está apenas vindo de páginas da web públicas, então você não pode fazer nada seguro a partir dessas páginas da web públicas porque, como você parece já saber, existem sem segredos em páginas da web públicas. Então, o que você pode fazer em suas páginas da web, qualquer pessoa também pode.
jfriend00
28
Tem certeza de que tem um problema de limitação de taxa para resolver no uso de dogfood? Cada usuário que usa seu site e suas páginas da web deve parecer um usuário completamente diferente do seu código de limitação de taxa. Portanto, certifique-se de que cada página da web siga as regras normais de limitação de taxa por si só e você estará bem. Supondo que seu limite de taxa seja por cliente, um usuário não terá nada a ver com outro usuário.
jfriend00
6
Por que você não considera uma solução de gerenciamento de API que fornece limitação de taxa e controle de fluxo por usuário, por função / permissão ou escopo de aplicativo. Por exemplo, wso2 api manger
MiddlewareManiac
3
Possível duplicata de Taxa de limitação de API com uma exceção especial
gastador de
28
Seu dogfooding descobriu um problema significativo com sua API pública (que é o limite de taxa muito baixo) e, em vez de corrigi-lo, você está tentando contorná-lo. Por que usar dogfood se você vai ignorar os problemas que encontrar?
user253751

Respostas:

93

Já que seu próprio cliente JavaScript está acessando a API diretamente, qualquer um será capaz de ver o que está fazendo e imitar, incluindo usar a mesma chave de API. Você pode tentar tornar isso mais difícil, por exemplo, ofuscando seu código ou colocando vários obstáculos no caminho, mas você e a pessoa que está tentando restringir têm fundamentalmente o mesmo acesso. Em vez de tentar criar uma diferença de privilégios, você precisará construir um sistema onde seja totalmente OK que o cliente não oficial use todo o acesso em seu escopo, mas o sistema seja organizado de forma que o uso oficial em todos os clientes seja maior.

Isso geralmente é feito com tokens de acesso por usuário, ao contrário de um token para todo o aplicativo. O limite de cada token deve ser suficiente para o uso típico de sua API, mas restritivo para alguém que tenta abusar dele. Por exemplo, 100 chamadas por minuto podem ser mais do que suficientes para suportar a navegação normal, mas se eu quiser atrapalhar você, não posso fazer isso de forma eficaz com esse orçamento.

Sempre haverá uma corrida armamentista - posso contornar o limite criando muitas contas de usuário de bot. Isso, porém, é um problema bastante resolvido se você apenas adicionar um captcha ao seu fluxo de inscrição, com uma pequena despesa para o ser humano real. Quando você entra nesses cenários, tudo é apenas uma troca entre conveniência e restrição. Você nunca encontrará algo totalmente à prova de balas, então concentre-se em torná-lo bom o suficiente e espere até que alguém o explore para saber onde estão os buracos.

Kristján
fonte
8
Aceitando isso como a melhor resposta. O caminho que decidimos seguir é usar tokens JWT com expiração menor e aumentar o limite de taxa dessas chamadas. Codificaremos algumas informações adicionais no token para permitir que o back-end saiba do limite de taxa mais alto. Como esses tokens são assinados com segurança no back-end, não deve haver problemas com falsificação. Alguém ainda poderia usar o token, mas ele expiraria depois de alguns dias e, portanto, manter qualquer tipo de bot seria mais difícil de fazer.
Jason Waldrip
33

Se isso estiver causando um problema, causará um problema ao seu ecossistema de desenvolvedores (por exemplo, quando eles tentarem desenvolver uma IU alternativa). Se você está realmente comendo sua própria comida de cachorro, faça com que a API (e a limitação de taxa) funcione para seu aplicativo. Aqui estão algumas sugestões:

  • Não limite a taxa por endereço IP. Em vez disso, limite de taxa por algo associado ao usuário, por exemplo, seu ID de usuário. Aplique o limite de taxa no estágio de autenticação.

  • Projete sua API para que os usuários não precisem chamá-la continuamente (por exemplo, dar uma chamada de lista que retorna muitos resultados, em vez de uma chamada repetida que retorna um item de cada vez)

  • Projete seu aplicativo da web com as mesmas restrições que você espera que seu ecossistema de desenvolvedor tenha, ou seja, certifique-se de projetá-lo dentro de taxas de limitação razoáveis.

  • Certifique-se de que seu back-end seja escalonável (de preferência horizontalmente) para que você não precise impor uma limitação em níveis tão baixos que realmente causem um problema para uma IU.

  • Certifique-se de que seu controle de fluxo tenha a capacidade de lidar com explosões, bem como limitar o abuso de longo prazo.

  • Certifique-se de que sua limitação execute ações sensatas, adaptadas ao abuso que você deseja remover. Por exemplo, considere colocar na fila ou atrasar abusadores moderados em vez de recusar a conexão. A maioria dos front-ends da web abrirá apenas quatro conexões simultâneas de uma vez. Se você atrasar uma tentativa de abrir um quinto, só encontrará o caso em que eles estão usando uma CLI ao mesmo tempo que o cliente da web (ou dois clientes da web). Se você atrasar a n-ésima chamada de API sem uma lacuna em vez de falhar, o usuário final verá as coisas ficarem mais lentas em vez de parar. Se você combinar isso com apenas enfileirar N chamadas API de uma vez, você só atingirá pessoas que estão paralelizando um grande número de chamadas API, o que provavelmente não é o comportamento que você deseja - por exemplo, 100 chamadas API simultâneas, então um intervalo de uma hora é normalmente longe pior do que 100 chamadas de API sequenciais em uma hora.

Isso não respondeu à sua pergunta? Bem, se você realmente precisa fazer o que está pedindo, limite a taxa no estágio de autenticação e aplique um limite de taxa diferente com base no grupo em que seu usuário se encaixa. Se estiver usando um conjunto de credenciais (usado por seus desenvolvedores e equipe de controle de qualidade), você obterá um limite de taxa mais alto. Mas você pode ver imediatamente porque isso o levará inevitavelmente ao seu ecossistema, vendo problemas que o desenvolvedor e a equipe de controle de qualidade não veem.

abligh
fonte
11

Compre seu produto. Torne-se um cliente pago de você mesmo.

"O acesso anônimo à nossa API tem um limite muito baixo para chamadas API por hora, enquanto nossos clientes pagos têm permissão para mais de 1000 chamadas por hora ou mais."

Isso também ajuda a testar o sistema da perspectiva do cliente.

jkdev
fonte
1
A resposta óbvia. Sem trapaça ou fingimento aqui!
wizzwizz4
9

Infelizmente, não existe uma solução perfeita para isso.

A abordagem geral é normalmente fornecer um spoofableforma para os clientes se identificarem (por exemplo, um identificador, versão e chave de API - por exemplo), para os clientes registrarem informações sobre si mesmos que podem ser usadas para limitar o acesso (por exemplo, o cliente é um servidor em um determinado intervalo de endereços IP, portanto, permita apenas chamadores nesse intervalo; por exemplo, o cliente é JavaScript, mas entregue apenas a uma categoria específica de navegador, portanto, permita o acesso apenas a solicitações HTTP que especificam certas strings de agente do usuário; etc.) e, em seguida, use o aprendizado de máquina / padrão reconhecimento para detectar o uso anômalo que provavelmente é um cliente falsificado e, em seguida, rejeitar o tráfego desses clientes falsificados (ou confirmar com os clientes que esses usos não são de fato provenientes do cliente legítimo, substituir suas credenciais falsificáveis ​​e, em seguida, proibir o tráfego adicional usando o mais antigo credenciais falsificadas).

Você pode tornar um pouco mais difícil falsificar usando várias camadas de chave. Por exemplo, você fornece uma credencial de longa duração que reside em um servidor (e que só pode ser usada em um conjunto limitado de intervalos de endereços IP) para fazer uma chamada de API que registra informações sobre o cliente (por exemplo, o agente do usuário) e retorna uma chave do lado do cliente de vida mais curta que é distribuída em JavaScript para uso no cliente para solicitações de API do lado do cliente. Isso também é imperfeito (um spoofer poderia emitir a mesma chamada de servidor para obter a credencial), mas será mais difícil se a chave de API retornada for incluída em JavaScript ou HTML ofuscado (e frequentemente alterado) (o que tornaria difícil para extrair de forma confiável da resposta). Isso também fornece uma maneira de detectar falsificação mais facilmente; a chave do lado do cliente agora está ligada a um cliente específico (por exemplo

Michael Aaron Safyan
fonte
8

Supondo que o aplicativo em questão deve ser aberto publicamente, você não tem muita escolha:

Escolha outra maneira de demonstrar o poder de sua API.Por exemplo, escreva um aplicativo e compartilhe seu código-fonte, mas não execute esse código. No entanto, certifique-se de que esteja bem documentado, para que qualquer pessoa possa implantá-lo e vê-lo funcionando (sujeito a limitação).

O aplicativo que você executa precisa ser refatorado para evitar solicitações de API do lado do cliente e ser mais renderizado pelo servidor. Você ainda pode usar sua API como dogfood, mas não de maneira óbvia - faça solicitações seguras para a API sem aceleração do lado do servidor.

Ajuste a limitação de taxa para permitir que seu aplicativo funcione e invista na otimização de desempenho para lidar com a carga.

E sim, tenha a API principal livre de aceleração em primeiro lugar e mantenha-a dentro de uma rede privada. Acelerar em uma camada separada acessível ao público.

Anton Strogonoff
fonte
4

Você pode criar uma instância separada da IU e da API sem aceleração e, em seguida, restringir o acesso a endereços IP vindos de sua organização?

Por exemplo, implante tudo atrás de seu firewall corporativo e anexe o aplicativo ao mesmo banco de dados que a instância pública se você precisar compartilhar dados entre as instâncias.

Peter Mortensen
fonte
4

Você pode tentar gerar um ID de sessão único, vinculado a um determinado endereço IP / usuário e com tempo de vida limitado. Quando um usuário baixa o código JavaScript do front-end do aplicativo, injete o ID de sessão gerado no código-fonte JavaScript. O ID da sessão será anexado a cada solicitação para sua API e o limite de taxa é levantado.

O ID não pode ser simplesmente copiado para falsificação, porque ele só é válido para um único endereço IP, usuário e por um período limitado de tempo. Portanto, um adversário teria que chamar sua página e filtrar a chave de sua fonte JavaScript ou de interceptar a solicitação Ajax toda vez que um novo usuário quisesse usá-la.

Outra opção:

Configure um proxy para seu próprio aplicativo e use a ofuscação. As solicitações Ajax para o proxy usam nomes diferentes das chamadas API reais e o proxy os traduz de volta. Portanto, seu aplicativo não chamariagetDocument em sua API real, mas chamaria getFELSUFDSKJEem seu proxy. O proxy traduzirá essa chamada de volta para getDocument e a encaminhará para a API de taxa limitada real.

Sua API real não limitará a taxa de solicitações do proxy.

E para que outras pessoas não usem seu proxy para seus próprios aplicativos, você altera o esquema de ofuscação diariamente. Os nomes de chamada ofuscados podem ser gerados automaticamente em seu código-fonte JavaScript e configurados no proxy.

Um cliente que deseja usar isso também precisa acompanhar as mudanças de ofuscação para usar o proxy. E você ainda pode usar cabeçalhos de referência e semelhantes para registro, para que possa encontrar pessoas usando seu proxy. Ou detecte-os ao alterar o esquema de ofuscação.

Falco
fonte
3
  • Lista de permissões de endereços IP de origem
  • Use uma VPN , coloque membros da VPN na lista de permissões
  • Solução de proxy ou complemento de navegador que adiciona cabeçalhos HTTP deve funcionar se você puder proteger o proxy e não estiver preocupado com ataques MITM que farejam o tráfego
  • Qualquer solução que envolva segredos pode mitigar o impacto dos vazamentos, girando os segredos diariamente
the8472
fonte
Essas soluções não se aplicam a um cliente Web front-end. Perfeito se o acesso à API for no back-end.
Jason Waldrip
@jason, todos eles podem ser aplicados a um front
the8472
2

Configure várias contas e escolha uma delas aleatoriamente a cada solicitação ou altere a que você usa a cada hora. Desta forma, você pode distribuir a carga pelas ncontas, dando-lhe nlimites até vezes mais elevados.

Tenha cuidado para não desligar-se acidentalmente se estiver tentando encontrar outros usuários fazendo isso, se não for permitido aos clientes.

Filip Haglund
fonte