¿Utiliza tablas IP o ruta nula para incluir en la lista negra aproximadamente 1 millón de direcciones IP?

22

Me he encontrado con una situación en la que un cliente necesita incluir en la lista negra un conjunto de poco menos de 1 millón de direcciones IP individuales (sin subredes), y el rendimiento de la red es una preocupación. Si bien conjeturaría que las reglas de IPTables tendrían un menor impacto en el rendimiento que las rutas, eso es solo una conjetura.

¿Alguien tiene alguna evidencia sólida u otra justificación para favorecer las tablas IP o el enrutamiento nulo como solución para poner en una lista negra largas listas de direcciones IP? En este caso, todo está automatizado, por lo que la facilidad de uso no es realmente una preocupación.

EDITAR 26-nov-11

Después de algunas pruebas y desarrollo, parece que ninguna de estas opciones es viable. Parece que tanto las búsquedas de ruta como las iptables realizan búsquedas lineales a través del conjunto de reglas y tardan demasiado tiempo en procesar tantas reglas. En el hardware moderno, poner elementos de 1M en una lista negra de iptables ralentiza el servidor a aproximadamente 2 docenas de paquetes por segundo. Entonces, las tablas IP y las rutas nulas están fuera.

ipset, según lo recomendado por Jimmy Hedman, sería genial, excepto que no le permite rastrear más de 65536 direcciones en un conjunto, por lo que ni siquiera puedo tratar de usarlo a menos que alguien tenga alguna idea.

Aparentemente, la única solución para bloquear esta cantidad de IP es realizar una búsqueda indexada en la capa de aplicación. ¿No es así?


Más información:

El caso de uso en este caso es bloquear una lista de "delincuentes conocidos" de direcciones IP para que no accedan al contenido estático en un servidor web. FWIW, hacer el bloqueo a través de Apache Deny fromes igualmente lento (si no más) ya que también hace un escaneo lineal.


FYI: La solución de trabajo final fue usar mod_rewrite de apache junto con un mapa de Berkeley DB para realizar búsquedas en la lista negra. La naturaleza indexada de las bases de datos de Berkeley permitió que la lista escalara con el rendimiento O (log N).

tylerl
fuente
55
¿No está ipset ( ipset.netfilter.org ) menos diseñado para manejar este tipo de problema?
Jimmy Hedman el
@JimmyHedman: Deberías hacer eso una respuesta. Y luego agregue una sugerencia para hacer una referencia haciendo las 3 formas :)
MikeyB
Tengo curiosidad si puede dar un poco más de información sobre qué problema está tratando de resolver. ¿Quizás bloquear direcciones IP de 1M no es la forma de solucionar el problema?
SpacemanSpiff
Sería de gran ayuda saber por qué desea bloquear tantas direcciones y si desea filtrar el tráfico de ENTRADA o ADELANTE.
Juliano
Aquí puede ver cómo ipset hace que las reglas de iptables sean aproximadamente 11 veces más rápidas que las reglas normales de iptables. daemonkeeper.net/781/mass-blocking-ip-addresses-with-ipset Espero que esta ayuda.
Alien Torres

Respuestas:

15

intente usar iptables y construir un árbol de niveles múltiples para disminuir el número de búsquedas.

iptables -N rules_0_0_0_0_2
iptables -N rules_64_0_0_0_2
iptables -N rules_128_0_0_0_2
iptables -N rules_192_0_0_0_2
iptables -N rules_0_0_0_0_4
iptables -N rules_16_0_0_0_4

iptables -A INPUT -p tcp --dport 80 -s 0.0.0.0/2 -j rules_0_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 64.0.0.0/2 -j rules_64_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 128.0.0.0/4 -j rules_128_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 192.0.0.0/4 -j rules_192_0_0_0_2

iptables -A rules_0_0_0_0_2 -s 0.0.0.0/4 -j rules_0_0_0_0_4
iptables -A rules_0_0_0_0_2 -s 16.0.0.0/4 -j rules_16_0_0_0_4

y así sucesivamente - agregando niveles de anidamiento; obviamente necesitará una forma automática de construir las reglas y debería tener cadenas solo para las redes donde tiene uno o más delincuentes; de esta manera puede reducir la cantidad de búsquedas que deben realizarse de manera bastante significativa y creo que podría En realidad funciona.

pQd
fuente
Esto suena como si pudiera funcionar, reduciendo efectivamente la complejidad de tiempo de la búsqueda de la regla del firewall de O (n) a O (log n), construyendo efectivamente un árbol de búsqueda en iptables.
Per von von Zweigbergk
Si decide seguir esta ruta, probablemente sea útil usar algún algoritmo para construir un árbol de búsqueda binario balanceado de la lista de direcciones IP, y luego simplemente descartar la estructura de ese árbol de búsqueda como un conjunto de reglas de IPtables.
Per von Zweigbergk
@Per von Zweigbergk - de hecho ... o simplemente pode el árbol temprano donde no hay necesidad de realizar búsquedas más profundas. aunque cargar esa cantidad de reglas impías tomará mucho tiempo.
pQd
Este es un muy buen enfoque. Obviamente, requiere un poco de procesamiento para mantenerse, pero creo que es la idea correcta.
tylerl
3
@pQd después de fallas anteriores con iptables et al., implementé una solución en apache usando un RewriteMap con la base de datos Berkeley. Pero mi mecanismo más rápido usando iptables en un bucle cargó alrededor de 100 reglas por segundo, mientras que iptables-restore hizo todo el conjunto en aproximadamente 4 segundos. Esto está en una computadora de escritorio de primera línea. El mecanismo RewriteMap tiene un impacto indetectable bajo en el rendimiento.
tylerl
11

Esto es exactamente para lo que ipsetsirve.

Desde su sitio web http://ipset.netfilter.org/ :

Si quieres

  • almacenar múltiples direcciones IP o números de puerto y compararlas con la colección por iptables de una sola vez;
  • actualizar dinámicamente las reglas de iptables contra direcciones IP o puertos sin penalización de rendimiento;
  • Exprese direcciones IP complejas y conjuntos de reglas basados ​​en puertos con una sola regla de iptables y aproveche la velocidad de los conjuntos de IP

entonces ipset puede ser la herramienta adecuada para usted.

Está escrito por un miembro del equipo central de netfilter, Jozsef Kadlecsik (quien también escribió el objetivo RECHAZAR), así que esta es la mejor opción que se me ocurre.

Incluso se incluye en los núcleos recientes.

cstamas
fuente
Hasta donde he visto, ipset alcanza un máximo de 65k direcciones IP. ¿Hay algún tipo de conjunto que pueda manejar entradas de 1M?
tylerl
77
Si utiliza el tipo de conjunto hash: ip, puede tener un gran número de direcciones. Intenté 1000000 y el rendimiento fue bastante bueno. Si configura una regla -m state --statable ESTABLISHED antes de verificar su conjunto, puede asegurarse de que solo verifique el conjunto en nuevas conexiones que aumentarían el rendimiento cuando se trata con una gran cantidad de paquetes.
Matthew Ife
Sin embargo, vale la pena mencionar que el uso de memoria de un ipset con direcciones 1M comienza a ser grande. De acuerdo con esta publicación en la lista de correo de netfilter, la fórmula actual de 2015 para el tamaño de hash de ipset es H * 40byte + (N/4 + N%4) * 4 * element sizede aproximadamente 64 MB para direcciones 1M en un hash de ranura de 1,5 m. El uso de la solución apache / berkdb almacena los datos en el disco y solo carga las páginas de las direcciones activas.
M Conrad
5

No lo he probado yo mismo, pero cuando escuché la descripción de su problema, pensé instantáneamente " pf" (a partir de OpenBSD).

pftiene el concepto de tablas de direcciones que pueden ser lo que estás buscando.

Según una investigación muy superficial que hice, parece que esto tiene el potencial de escalar mejor que ipset. De acuerdo con el capítulo de preguntas frecuentes de PF sobre Opciones de tiempo de ejecución , listo para usar sin ajustar, pf admite un total de 1,000 tablas, con un total de 200,000 entradas en todas las tablas de forma predeterminada. (100.000 si el sistema tiene <100 MB de memoria física). Esto me lleva a creer que al menos vale la pena considerar probar esto para ver si funciona en algún tipo de nivel útil.

Por supuesto, supongo que está ejecutando sus servidores en Linux, por lo que debería tener una caja de firewall separada que ejecute algunos sistemas operativos con pf (como OpenBSD o FreeBSD). También podría mejorar el rendimiento eliminando cualquier tipo de filtrado de paquetes con estado.

Per von Zweigbergk
fuente
Convertir la arquitectura del servidor del cliente a BSD no es realmente una opción. Pensando fuera de la caja al menos, sin embargo.
tylerl
2
No tendría que convertir toda la arquitectura del servidor a BSD, sería suficiente construir un firewall para colocarlo frente al servidor real. (Suficientemente fácil de hacer en una máquina virtual.)
Per von Zweigbergk
2

¿Has investigado usando un FIB_TRIE en lugar de FIB_HASH.

FIB_TRIE debería escalar mucho mejor para sus recuentos de prefijos. (Las rutas nulas / 32s siguen siendo prefijos, solo que muy específicas)

Es posible que necesite compilar su propio núcleo para usarlo, pero ayuda.

Notas FIB_TRIE

Joel K
fuente
2

Para la posteridad: según los ipsetdocumentos, el tamaño predeterminado de un conjunto es 65536, esto se puede cambiar por opciones.

maxelem Este parámetro es válido para el comando de creación de todos los conjuntos de tipos hash. Define el número máximo de elementos que se pueden almacenar en el conjunto, por defecto 65536. Ejemplo:ipset create test hash:ip maxelem 2048.

Puse esto aquí ya que no puedo comentar todavía.

plitter
fuente
1

Algunas notas útiles para cualquier persona que se encuentre con este problema en el futuro:

En primer lugar, no analice el tráfico que no necesita. Si está bloqueando el tráfico TCP, por ejemplo, solo filtre los paquetes SYN, de esa manera solo golpeará el filtro una vez por conexión. Puede usarlo -m statesi lo desea, pero el seguimiento de la conexión tiene su propia sobrecarga que puede evitar si el rendimiento es un problema.

En segundo lugar, poner un millón de reglas en iptables lleva mucho tiempo: varios minutos. Si necesita rastrear tantas entidades, probablemente sea mejor mantenerlo fuera de netfliter. El gran tamaño del conjunto de reglas hace la diferencia.

Tercero, el objetivo es evitar exploraciones lineales; pero desafortunadamente, tanto iptables como iproute2 son inherentemente lineales. Puede dividir sus reglas al estilo de árbol binario en una gran cantidad de cadenas, lo que limita la cantidad de reglas que debe consultar, pero aun así, iptables no es adecuado para este tamaño de problema. Se trabajará , pero es un desperdicio de recursos valiosos.

Cuarto, y lo más importante, empujar su carga de trabajo al espacio de usuario no es una mala idea. Esto le permite escribir su propio código apretado o usar una solución estándar que esté ajustada a su conjunto de problemas. Mi propia solución a este problema, como se mencionó, fue usar búsquedas de BDB activadas a través del sistema mod_rewrite de apache. Esto tenía el beneficio adicional de activar solo una búsqueda por sesión, y solo después de que se hubiera enviado una solicitud válida. En este caso, el rendimiento fue extremadamente rápido y el costo de la lista de bloqueo fue casi insignificante.

Puede hacer una manipulación similar del espacio de usuario con iptables utilizando el -j QUEUEobjetivo junto con libnetfilter_queue. Esta herramienta es poderosa, simple y poco documentada. Recomendaría leer tanto como sea posible de tantas fuentes como pueda encontrar, ya que hay una gran cantidad de material interesante disperso en la web que no forma parte de ninguna documentación oficial.

tylerl
fuente