Eu me deparei com uma situação em que um cliente precisa colocar na lista negra um conjunto de pouco menos de 1 milhão de endereços IP individuais (sem sub-redes), e o desempenho da rede é uma preocupação. Embora eu conjecture que as regras do IPTables teriam menos impacto no desempenho do que as rotas, isso é apenas conjectura.
Alguém tem alguma evidência sólida ou outra justificativa para favorecer o IPTables ou o roteamento nulo como solução para colocar listas longas de endereços IP na lista negra? Nesse caso, tudo é automatizado, portanto, a facilidade de uso não é realmente uma preocupação.
EDIT 26-Nov-11
Após alguns testes e desenvolvimento, parece que nenhuma dessas opções é viável. Parece que as pesquisas de rota e as tabelas de ip fazem pesquisas lineares no conjunto de regras e demoram muito tempo para processar essas muitas regras. No hardware moderno, colocar 1 milhão de itens em uma lista negra do iptables reduz o servidor para cerca de 2 dúzias de pacotes por segundo. Portanto, IPTables e rotas nulas estão fora.
ipset
, como recomendado por Jimmy Hedman, seria ótimo, exceto que ele não permite que você rastreie mais de 65536 endereços em um conjunto, por isso não posso nem tentar usá-lo, a menos que alguém tenha alguma idéia.
Aparentemente, a única solução para bloquear tantos IPs é fazer uma pesquisa indexada na camada de aplicação. Não é assim?
Mais Informações:
O caso de uso nesta instância está impedindo que uma lista de endereços IP "ofensores conhecidos" acesse o conteúdo estático em um servidor da web. FWIW, fazer o bloqueio através do Apache Deny from
é igualmente lento (se não mais), como também faz uma varredura linear.
FYI: A solução final de trabalho foi usar o mod_rewrite do apache em conjunto com um mapa de banco de dados de berkeley para fazer pesquisas na lista negra. A natureza indexada dos bancos de dados de berkeley permitiu que a lista fosse dimensionada com o desempenho de O (log N).
Respostas:
tente usar o iptables e criar uma árvore de vários níveis para diminuir o número de pesquisas.
e assim por diante - adicionando níveis de aninhamento; Obviamente, você precisará de uma maneira automática de criar as regras e deverá ter cadeias apenas para as redes em que há um ou mais infratores - dessa forma, você pode reduzir o número de pesquisas que precisam ser feitas de maneira bastante significativa e acho que pode realmente funciona.
fonte
É exatamente
ipset
para isso.No site http://ipset.netfilter.org/ :
Se você quiser
então o ipset pode ser a ferramenta adequada para você.
Ele foi escrito por Jozsef Kadlecsik, membro da equipe principal do netfilter (que também escreveu o alvo REJECT). Portanto, essa é a melhor escolha que posso pensar.
Está incluso nos kernels recentes.
fonte
H * 40byte + (N/4 + N%4) * 4 * element size
de aproximadamente 64 MB para endereços de 1 milhão em um hash de slot de 1,5 m. O uso da solução apache / berkdb armazena os dados no disco e carrega apenas as páginas dos endereços ativos.Eu não testei isso sozinho, mas quando ouvi a descrição do seu problema, pensei "
pf
" imediatamente (como no OpenBSD).pf
tem o conceito de tabelas de endereços que podem ser exatamente o que você está procurando.De acordo com uma pesquisa muito superficial que eu fiz, parece que isso tem o potencial de ter uma escala melhor do que
ipset
. De acordo com o capítulo das Perguntas frequentes sobre PF em Opções de tempo de execução , pronto para uso sem ajuste, o pf suporta um total de 1.000 tabelas, com um total de 200.000 entradas em todas as tabelas por padrão. (100.000 se o sistema tiver <100 MB de memória física). Isso me leva a acreditar que vale a pena considerar tentar testar isso para ver se funciona em algum tipo de nível útil.Claro, estou assumindo que você esteja executando seus servidores no Linux, então você teria que ter uma caixa de firewall separada executando algum sistema operacional com pf (como OpenBSD ou FreeBSD). Você também pode melhorar o rendimento eliminando qualquer tipo de filtragem de pacotes com estado.
fonte
Você investigou usando um FIB_TRIE em vez de FIB_HASH.
FIB_TRIE deve escalar muito melhor para sua contagem de prefixos. (As rotas nulas do / 32s ainda são prefixos, apenas muito específicas)
Você pode precisar compilar seu próprio kernel para usá-lo, mas isso ajuda.
Notas FIB_TRIE
fonte
Para a posteridade: de acordo com os
ipset
documentos, o tamanho padrão de um conjunto é 65536, isso pode ser alterado por opções.Coloquei isso aqui, pois ainda não posso comentar.
fonte
Algumas notas úteis para quem se deparar com esse problema no futuro:
Primeiro de tudo, não analise nenhum tráfego desnecessário. Se você estiver bloqueando o tráfego TCP, por exemplo, filtre apenas os pacotes SYN, dessa forma, você só acessa o filtro uma vez por conexão. Você pode usar
-m state
se quiser, mas o rastreamento de conexão tem sua própria sobrecarga que você pode evitar se o desempenho for um problema.Segundo, colocar um milhão de regras no iptables leva muito tempo: vários minutos. Se você precisar rastrear muitas entidades, é melhor mantê-lo fora do netfliter. O tamanho do conjunto de regras faz a diferença.
Terceiro, o objetivo é evitar verificações lineares; mas, infelizmente, o iptables e o iproute2 são inerentemente lineares. Você pode dividir suas regras no estilo de árvore binária em um grande número de cadeias, o que limita o número de regras que você precisa consultar, mas mesmo assim o iptables não é adequado para esse tamanho de problema. Ele vai trabalhar , mas é um desperdício de recursos valiosos.
Quarto, e mais importante, levar sua carga de trabalho ao espaço do usuário não é uma má idéia. Isso permite que você escreva seu próprio código restrito ou use uma solução pronta para uso que esteja ajustada ao seu conjunto de problemas. Minha própria solução para esse problema, como mencionado, foi usar pesquisas BDB acionadas pelo sistema mod_rewrite do apache. Isso teve o benefício adicional de acionar apenas uma pesquisa por sessão e somente após o envio de uma solicitação válida. Nesse caso, o desempenho foi extremamente rápido e o custo da lista de bloqueio foi quase insignificante.
Você pode fazer uma manipulação semelhante do espaço do usuário com o iptables usando o
-j QUEUE
destino em conjunto comlibnetfilter_queue
. Essa ferramenta é poderosa, simples e mal documentada. Eu recomendaria ler o máximo possível a partir de tantas fontes quanto possível, pois há muito material interessante espalhado pela Web que não faz parte de nenhuma documentação oficial.fonte