8.7.3.1.3. Extensiones

iptables dispone de algunas extensiones que amplían enormemente las posibilidades del cortafuegos. Repasaremos las más interesantes

8.7.3.1.3.1. limit

En general, las extensiones de limitación (limit, connlimit, haslimit) permiten establecer límites en el flujo de paquetes.

Extensión

Opción

limit

Límita el flujo de paquetes.

–limit

Ratio máximo admisible.

–limit-burst

Ráfaga mayor admisible.

iptables -A FORWARD -i eth0 -p tcp –syn -m limit –limit 5/s –limit-burst 10 -j ACCEPT

hashlimit

Limita el flujo de paquetes considerando el origen y el destino.

–hashlimit-mode

Qué parámetros se consideran para definir la condición entre srcip, srcport, dstip y dstport. Si no se especifica, el módulo se comporta como limit.

–hashlimit-upto

Ratio máximo admisible.

–hashlimit-burst

Ráfaga maypr admisible.

iptables -A FORWARD -m conntrack –ctstate DNAT -m hashlimit –hashlimit-upto 5/s –hashlimit-burst 10 –haslimit-mode srcip,dstip -j ACCEPT

connlimit

Límite de conexiones simultáneas.

–connlimit-upto

Número máximo de conexiones simultáneas con un mismo cliente.

iptables -A FORWARD -m conntrack –ctstate DNAT -m connlimit –connlimit-upto 3 -j ACCEPT

limit y hashlimit funcionan de forma semenjante: se establece un ratio medio (--limit, --hashlimit-upto) y un límite máximo para las ráfagas (--limit-burst, --hashlimit-burst) y el sistema funciona de forma semejante a como lo haría un embudo:

../../../_images/limit.png

El ratio representa el caudal de desagüe, pero el embudo posee un vaso que permite verter puntualmente más agua hasta un límite máximo. Cada paquete viene representado en el dibujo por una bolita, de modo que se pueden acomular como máximo el número de paquetes indicado con --limit-burst, lo que permite absorber una ráfaga intensa.

Ver también

Una aplicación práctica del uso de este módulo puede verse bajo el epígrafe dedicado a ataques DoS.

8.7.3.1.3.2. set

-s o -d permiten establecer condiciones al origen o el destino de los paquetes, pero admiten un argumento individual que a lo más nos permite expresar una red. Sin embargo, hay ocasiones en que nuestro propósito es referir un conjunto heterogéneo de direcciones (un caso típico es el del software fail2ban que veta accesos según detecta ataques). En estos casos, el número de direcciones IP puede ser considerable y, como cada dirección, requerirá una regla, el número de reglasd, también.

El módulo set junto a la orden ipset permite definir conjuntos de direcciones o puertos a los que dinámicamente se pueden ir añadiendo o eliminando integrantes; y que una única regla se limite a pedirle a iptables que busque dentro del conjunto.

Por ejemplo, supongamos que queremos permitir el acceso al servidor desde nuestras redes locales, lo cual sin el módulo sería así:

# iptables -A INPUT -s 192.168.128.0/24 -j ACCEPT
# iptables -A INPUT -s 192.168.129.0/24 -j ACCEPT
# iptables -A INPUT -s 192.168.130.0/24 -j ACCEPT
# iptables -A INPUT -s 192.168.134.0/24 -j ACCEPT
# iptables -A INPUT -s 192.168.135.0/24 -j ACCEPT

Ciertamente en este caso particular podríamos haber reducido las reglas jugando con las máscaras, pero el caso es que salen varias líneas de reglas y si otro fuera el caso, podrían ser miles. En cambio, si definiéramos, como se verá más adelante, un conjunto hash:net con ipset que contuviera todas esas redes, nos bastaría la siguiente regla:

# iptables -A INPUT -m set --match-set miredeslocales src -j ACCEPT

donde la creación del conjunto «miredeslocales» y la gestión de las redes que contiene se hace a través del command:ipset. Esto permite trabajar de forma más clara y eficiente.

ipset

ipset no forma parte de la instalación base, por lo que es necesaria su instalación manual:

# apt install ipset

Lo más básico y previo a cualquier uso es ser capaz de crear un conjunto, lo cual se hace a través del subcomando create:

ipset create <tipo_conjunto> <nombre_conjunto> <opciones_de_creacion>

donde tipo de conjunto indica qué valores contendrá. Por ejemplo, si quisiéramos almacenar simplemente una lista de redes, el tipo sería hash:net. En cambio, si dispusiéramos una lista de direcciones IP, podríamos usar hash:ip. Los conjuntos pueden ser algo más complejos. Por ejemplo, quizás quermos almacenar una lista de tuplas (IP, puerto); para lo cual existe el tipo hash:ip,port. Hay diversos tipos de conjuntos que pueden consultarse con la opción --help de ipset o en su página del manual.

También pueden incluirse opciones de creación que alteran el comportamiento del conjunto. Una muy útil es timeout, que permite indicar el tiempo en segundos que durará la entrada en el conjunto. Por ejemplo:

# ipset create bannedip hash:ip timeout 120

crea un conjunto llamado bannedip que contiene direcciones IP, las cuales se mantendrán en él durante dos minutos. Si no se hubiera añadido la opción, las direcciones se habrían mantenido indefinidamente a menos que las elimináramos manualmente. Para consultar el conjunto que acabamos de crear:

# ipset list bannedip
Name: bannedip
Type: hash:ip
Revision: 3
Header: family inet hashsize 1024 maxelem 65536 timeout 120
Size in memory: 16504
References: 0
Members:

Hecho esto, pueden añadirse IPs al conjunto:

# ipset add bannedip 80.80.80.80
# ipset add bannedip 80.80.80.81
# ipset add bannedip 80.80.80.82
# ipset add bannedip 80.80.80.80
ipset v6.23: Element cannot be added to the set: it's already added

Hemos añadido tres ips y la cuarta, al estar repetida, no. Si volvemos a consultar el conjunto veremos lo siguiente:

# ipset list bannedip
Name: bannedip
Type: hash:ip
Revision: 3
Header: family inet hashsize 1024 maxelem 65536 timeout 120
Size in memory: 16744
References: 0
Members:
80.80.80.81 timeout 94
80.80.80.82 timeout 94
80.80.80.80 timeout 92

O sea, lo mismo de antes y, además, los ips incluidas en el conjunto y el tiempo que falta para que salgan de él. Si esperamos lo suficiente:

# ipset list bannedip
Name: bannedip
Type: hash:ip
Revision: 3
Header: family inet hashsize 1024 maxelem 65536 timeout 120
Size in memory: 16744
References: 0
Members:

habrán desaparecido. Cuando al conjunto se le incluyó un tiempo de eliminación predeterminado, se puede añadir entradas que tengan otro distinto:

# ipset add bannedip 80.80.80.80 timeout 86400
# ipset list bannedip
Name: bannedip
Type: hash:ip
Revision: 3
Header: family inet hashsize 1024 maxelem 65536 timeout 120
Size in memory: 16584
References: 0
Members:
80.80.80.80 timeout 86397

Además, si se incluye la opción -exist y la entrada ya existe, en vez de generar un error, se reseteará el contador de tiempo:

# ipset -exist add bannedip 80.80.80.80
# ipset list bannedip
Name: bannedip
Type: hash:ip
Revision: 3
Header: family inet hashsize 1024 maxelem 65536 timeout 120
Size in memory: 16584
References: 0
Members:
80.80.80.80 timeout 118

Del mismo modo que creamos un conjunto, podemos destruirlo:

# ipset destroy bannedip

Uso del módulo

La utilidad de crear conjuntos está en usarlos en las reglas de iptables mediante el módulo set:

Extensión

Opción

Descripción

set

–match-set

Comprueba si el dato se encuentre en el conjunto. Debe añadirse el nombre del conjunto y src o dst indican si se tomarán datos de origen o destino.

iptables -A INPUT -m set –match-set bannedip src -j DROP

–return-nomatch

Invierte el resultado de la operación.

iptables -A INPUT -M set –match-set bannedip –return-nomatch src -j DROP

Además, se define un objeto que permite manipular el contenido de los conjuntos, lo cual posibilita gestionarlos de forma dinámica según analice iptables el tráfico:

Tabla

Objetivo

Descripción

Todas

SET

–add-set

Añade un dato al conjunto. Debe expresarse el nombre del conjunto y si son datos de origen o destino. Para el ejemplo se supondrá que bannedconn es de tipo hash:ip,port.

iptables -A INPUT -m mark –mark 0x1 -j SET –add-set bannedconn src,dst

–del-set

Elimina una entrada del conjunto.

iptables -A INPUT -m mark –mark 0x2 -j SET –del-set bannedconn src,dst

–timeout

Añade un tiempo de vida a la entrada distinto al predefinido del conjunto.

iptables -A INPUT -m mark –mark 1 -j SET –add-set bip src –timeout 120

–exist

Al añadir la entrada, resetea el contador de tiempo si esta ya existía.

iptables -A INPUT -m mark –mark 0x1 -j SET –add-set bannedip src –exist

8.7.3.1.3.3. recent

recent es un módulo de iptables que permite crear una lista dinámica con las direcciones IP (en principio, direcciones IP de origen) que establecen conexión con nuestro servidor y toma decisiones en base a ello. Por ello, es útil para poner en práctica tanto el port-knocking como la limitación de accesos. Antes de ello, estudiemos brevemente las posibilidades del módulo:

Nota

En todos los casos, la IP es la de origen.

Extension

Opción

Descripción

recent

–set

Añade la dirección IP a la lista o actualiza la entrada si ya estaba.

iptables -A INPUT -i eth0 -p icmp -m recent –set -j DROP

–rcheck

Comprueba si la dirección IP se encuentra en la lista

iptables -A INPUT -i eth0 -m recent –rcheck -j DROP

–update

Además de comprobar, actuailiza la lista para añadir el instante de tiempo como la última vez que se ha visto la IP.

iptables -A INPUT -i eth0 -m recent –update -j DROP

–remove

Elimina la IP de la lista.

iptables -A INPUT -i eth0 -m recent –remove -j DROP

–name <NOMBRE>

Indica el nombre de la lista. Si no incluye, la lista es «DEFAULT».

iptables -A INPUT -i eth0 -p icmp -m recent –set –name PING -j DROP

–seconds <SEGUNDOS>

Restringe la búsqueda en la lista sólo a los últimos segundos que se especifique. Por tanto, si se añade, --seconds 60, la coincidencia sólo se producirá si se añadió la IP en el último minuto.

–hitcount <N>

La búsqueda tendrá éxito sólo si la dirección se encuentra en la lista el número de veces indicado. Por supuesto, puede usar en conjunción con --seconds.

–reap

Usado en conjunción con --seconds provoca que se eliminen de la lista las entradas de la IP anteiores al periodo de tiempo indicado.

–rdest

Usa la IP de destino, en vez de de la de origen.

–mask <MASCARA>

Máscara que debe aplicarse a la lista de direcciones.

Tengase en cuenta que:

  • --set, --update, --remove, además de condiciones, provocan la manipulación de la lista. Como condiciones, --set siempre devuelve verdadero; --remove y --update, verdadero si la IP estaba en la lista.

  • Cuando se comprueba si la entrada existe (--rcheck o -update) es posible añadir --seconds, --hitcount y --reap.

Por otro lado, la listas pueden consultarse dentro del directorio /proc/net/xt_recent/ e incluso aplicar manualmente modificaciones sobre ellas según lo que expone la página de manual.

Para ilustrar el uso, tomemos y comentemos un par de ejemplos inspirados en los de la documentación oficial:

Ejemplo 1

iptables -A INPUT -m recent --rcheck --seconds 120 -j DROP
iptables -A INPUT -i eth0 -p icmp -m recent --set -j DROP

Con estas reglas, si una máquina cualquiera intentos hacernos ping por primera vez, la primera regla se evalúa a falso, ya que la IP no se encuentra aún en la lista DEFAULT. En consecuencia, este primer paquete prueba la segunda regla y al ser un paquete ping provocará la inclusión en la lista de la IP y, además, se rechazará el paquete, ya que --set siempre se evalúa a verdadero. A partir de la recepción de este paquete ICMP y durante 2 minutos cualquier paquete procedente de esta IP, sea de la naturaleza que sea, se rechazará al toparse con la primera regla. Pasados los dos minutos, la primera regla se evaluará a falso para paquetes procedentes de la esa IP y sólo si vuelve a mandar un paquete ICMP, volveremos a vetar la dirección.

En conclusión: si a una máquina se le ocurre mandarnos un paquete ICMP no podrá comunicarse con nosotros durante dos minutos.

Para comprobar cómo funciona, podemos probar a hacer una conexión SSH a esta máquina (IP 192.168.1.239) desde otra máquina (de IP 192.168.1.240): deberíamos acceder sin problemas, supuesto que haya un servidor SSH instalado, claro está. Ahora bien, si hacemos desde 192.168.1.240 un ping:

$ ping -c1 -W1 192.168.1.239

No recibiremos respuesta (ya que la segunda regla lo impide) y además habremos metido a la dirección de origen en la lista:

# cat /proc/net/xt_recent/DEFAULT
src=192.168.1.240 ttl: 1 last_seen: 4296132894 oldest_pkt: 1 4296132894

A partir de este momento y durante dos minutos, no podremos conectar desde 192.168.1.240. Si esperamos, volveremos a poder acceder por SSH a menos que en algún momento se nos ocurra volver a hacer un ping.

Ejemplo 2

iptables -A INPUT -m recent --update --seconds 120 -j DROP
iptables -A INPUT -i eth0 -p icmp -m recent --set -j DROP

El segundo ejemplo es semejante, pero al sustituir --rcheck por --update cualquier paquete que envíe la dirección IP renovará la entrada en la lista y, en consecuencia, la IP sólo dejará de estar vetada si pasa dos minutos sin enviarnos ningún paquete.

Ver también

Aplicaciones prácticas del uso de este módulo pueden consultarse bajo el epígrafe dedicado a los ataques de fuerza bruta.

8.7.3.1.3.4. Registro