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)
Verifique o referenciador em relação ao cabeçalho do host. - Falha porque o referenciador é facilmente falsificado.
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.
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?
fonte
Respostas:
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.
fonte
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.
fonte
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.
fonte
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
fonte
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.
fonte
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.
fonte
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 chamaria
getDocument
em sua API real, mas chamariagetFELSUFDSKJE
em 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.
fonte
fonte
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
n
contas, dando-lhen
limites 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.
fonte