Página siguiente Página anterior Índice general

7. Uso de iptables

iptables dispone de una página de manual bastante detallada (man iptables), por si necesita más detalles particulares. Aquellos de ustedes que estén familiarizados con ipchains, posiblemente quieran echar un vistazo a Diferencias entre iptables e ipchains; son bastante similares.

Con iptables se pueden hacer muchas cosas diferentes. Empezamos con tres cadenas de uso interno: INPUT, OUTPUT y FORWARD, que no se pueden borrar. Veamos las operacioes que se pueden hacer en todas las cadenas:

  1. Crear una nueva cadena (-N).
  2. Borrar una cadena vacía (-X).
  3. Cambiar la política de una cadena de uso interno (-P).
  4. Listar las reglas de una cadena (-L).
  5. Vaciar de reglas una cadena (-F).
  6. Poner a cero los contadores de paquetes y bytes de todas las reglas de una cadena (-Z).

Las reglas de una cadena se pueden manipular de varias maneras:

  1. Añadir una nueva regla a una cadena (-A).
  2. Insertar una nueva regla en alguna posición de la cadena (-I).
  3. Mover una regla a otra posición dentro de una cadena (-R).
  4. Borrar una regla de un sitio en particular de una cadena (-D).
  5. Borrar la primera regla que coincida con los parámetros dados en una cadena (-D).

7.1 Qué verá cuando el ordenador arranque

iptables puede ser un módulo, llamado («iptable_filter.o»), que debería cagarse de forma automática la primera vez que ejecute iptables. También lo puede hacer parte permanente del núcleo.

Antes de ejecutar alguna orden iptables (tenga cuidado: algunas distribuciones puede que ejecuten iptables en sus guiones de iniciación), no habrá reglas en ninguna de las cadenas de uso interno («INPUT», «FORWARD» y «OUTPUT»), todas las cadenas tendrán la política de ACCEPTar. Se puede alterar la política por defecto de FORWARD proporcionando la opción «forward=0» al módulo iptable_filter.

7.2 Operaciones sobre una sola regla

Este es el pan de cada día del filtrado de paquetes: la manipulación de reglas. Lo más común es que utilice las órdenes de agregar (-A) y eliminar (-D). Las otras (-I para insertar y -R para cambiar de sitio) son sólo extensiones de estos conceptos.

Cada regla especifica un conjunto de condiciones que debe cumplir el paquete, y qué hacer si se ajusta a ellas (un «objetivo»). Por ejemplo, podríamos querer descartar todos los paquetes ICMP que viniesen de la dirección IP 127.0.0.1. De manera que en este caso nuestras condiciones son que el protocolo sea ICMP y que la dirección de origen del paquete sea 127.0.0.1. Nuestro objetivo será «DROP».

127.0.0.1 es la interfaz «loopback», de la que dispondrá incluso si no tiene una conexión de red real. Puede usar el programa «ping» para generar tales paquetes (sencillamente envía paquetes ICMP de tipo 8 (echo request) que todos las máquinas cooperantes deberían responder cortésmente con un paquete ICMP de tipo 0 (echo reply)). Esto lo hace útil para las pruebas.

# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes
64 bytes from 127.0.0.1: icmp_seq=0 ttl=64 time=0.2 ms

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 1 packets received, 0% packet loss
round-trip min/avg/max = 0.2/0.2/0.2 ms
# iptables -A INPUT -s 127.0.0.1 -p icmp -j DROP
# ping -c 1 127.0.0.1
PING 127.0.0.1 (127.0.0.1): 56 data bytes

--- 127.0.0.1 ping statistics ---
1 packets transmitted, 0 packets received, 100% packet loss
#

Aquí puede ver que el primer «ping» tuvo éxito (el «-c 1» le indica a ping que sólo envíe un paquete).

Entonces añadimos (-A) a la cadena «INPUT», una regla que especifica que los paquetes que vengan de 127.0.0.1 («-s 127.0.0.1») con protocolo ICMP («-p icmp») deberíamos saltar a DROP («-j DROP»).

Luego probamos nuestra regla, usando el segundo ping. Habrá una pausa antes de que el programa se canse de esperar por una respuesta que nunca llegará.

Podemos borrar la regla de dos maneras. Primero, como sabemos que es la única regla en la cadena, podemos usar un borrado por número:

        # iptables -D INPUT 1
        #
Para borrar la regla número uno de la cadena INPUT.

La segunda manera es repetir la orden -A, pero cambiando -A por -D. Es útil cuando se tiene una compleja cadena de reglas y no queremo estar contándolas para averiguar que es la regla 37 la que queremos eliminar. En este caso, usaríamos:

        # iptables -D INPUT -s 127.0.0.1 -p icmp -j DROP
        #
La sintaxis de -D debe tener exactamente las mismas opciones que la orden -A (o -I, o -R). Si hay varias reglas idénticas en la misma cadena, sólo se borrará la primera.

7.3 Especificaciones del filtrado

Hemos usado «-p» para especificar el protocolo, y «-s» para la dirección de origen, pero podemos usar otras opciones para especificar las características de los paquetes. Lo que sigue es un compendio exhaustivo:

Especificar las direcciones IP de Origen y Destino

Las direcciones IP de origen («-s», «--source», o «--src») y destino («-d», «--destination», o «--dst») se pueden especificar de cuatro maneras. La más común es usar el nombre completo, tal como «localhost» o «www.linuxhq.com». La segunda manera es especificar la dirección IP, como «127.0.0.1».

Las tercera y cuarta maneras permiten especificar un grupo de direcciones IP, como «199.95.207.0/24» o «199.95.207.0/255.255.255.0». Ambas especifican cualquier dirección entre 199.95.207.0 y 199.95.207.255, ambas inclusive; los dígitos tras la «/» dicen qué partes de la dirección IP son significativas. «/32» o «/255.255.255.255» es la opción por defecto (coincide con toda la dirección IP). Para especificar cualquier dirección IP, se debe usar «/0», de esta manera:

        [ NOTA: «-s 0/0» es redundante en este caso. ]
        # iptables -A INPUT -s 0/0 -j DROP
        #

Se usa rara vez, ya que el efecto que se consigue en esta regla es lo mismo que si no se especificase la opción «-s».

Especificar una inversión

Hay muchos indicadores, como «-s» (o «--source») y «-d» («--destination») cuyos respectivos argumentos pueden ir precedidos por «!» (se pronuncia «not» o «no»), para que coincidan con direcciones que NO sean iguales a las proporcionadas. Por ejemplo, «-s ! localhost» coincide con cualquier paquete que no venga de localhost.

Especificar el protocolo

Se puede especificar el protocolo con el indicador «-p» (o «--protocol»). El protocolo puede ser un número (si sabe los valores numéricos) o un nombre en el caso especial de «TCP», «UDP» o «ICMP». No importa si lo pone en mayúscula o minúscula; «tcp» valdrá lo mismo que «TCP».

El nombre de protocolo puede ir prefijado de una «!», para invertirlo, de manera que «-p ! TCP» especifica paquetes que no sean TCP.

Especificar la Interfaz

Las opciones «-i» (o «--in-interface») y «-o» (o «--out-interface») especifican el nombre de una interfaz con la que coincidir. Una interfaz es el dispositivo físico por el que entra («-i») o sale («-o») un paquete. Puede usar la orden ifconfig para obtener una lista de las interfaces que están «up» (esto es, funcionando en ese momento).

Los paquetes que pasan por la regla INPUT no tienen un interfaz de salida, con lo que nunca se activará una regla de esta cadena que use «-o». De forma similiar, los paquetes que atraviesan OUTPUT no tienen interfaz de salida, de manera que ninguna regla que use «-i» en esta cadena funcionará.

Sólo los paquetes que pasan por la cadena FORWARD tienen a la vez interfaz de entrada y de salida.

Es perfectamente correcto especificar una interfaz que no existe en este momento; la regla no será activada por nada hasta que la interfaz empiece a funcionar. Esto es extremadamente útil con enlaces PPP de llamada (normalmente la interfaz ppp0) y similares.

Como caso especial, un nombre de interfaz que acabe en «+» coincidirá con todas las interfaces (que existan en ese momento o no) cuyo nombre empiece de esa manera. Por ejemplo, para especificar una regla que funcione para todas las interfaces PPP, se podría usar la opción -i ppp+.

El nombre de la interfaz puede ir precedido por «!» para coincidir con un paquete que no vaya por la(s) interfaz/ces especificada(s). does not match the specified interface(s).

Especificar fragmentos

Algunas veces ocurre que un paquete es demasiado grande para pasar por el cable de un solo golpe. Cuando esto ocurre, el paquete se divide en fragmentos, que se envían como varios paquetes. El otro extremo reensambla los fragmentos para reconstruir el paquete entero.

El problema de los fragmentos es que el primero de ellos tiene todos los campos de cabecera (IP + TCP, UDP e ICMP) que hay que examinar, pero los siguiente sólo tienen un subconjunto de la cabecara (IP sin los campos adicionales de protocolo). Por lo tanto, no es posible buscar cabeceras de protocolos (como se hace con las extensiones TCP, UDP e ICMP) en los siguientes fragmentos.

Si está haciendo un seguimiento de conexión o NAT, entonces se reunirán todos los fragmentos antes de que alcancen el código de filtrado de paquetes, de manera que no se deba preocupar por ellos.

Por otro lado, es importante comprender cómo son tratados los fragmentos por las reglas de filtrado. Cualquier regla de filtrado que pida información que no tenemos no será activada. Esto significa que el primer fragmento se trata como cualquier otro paquete. El segundo y los siguientes no. Por tanto una regla que diga -p TCP --sport www (que especifica como puerto origen el «www») nunca será activada por un fragmento (excepto el primero). Tampoco la regla opuesta -p TCP --sport ! www.

Sin embargo, podemos especificar una regla específicamente para el segundo fragmento y los siguientes, usando la opción «-f» (o «--fragment»). También es válido especificar que una regla no se va a aplicar al segundo fragmento ni a los siguientes, precediendo «-f» con «!».

Normalmente se considera seguro dejar pasar el segundo fragmento y siguientes, ya que el filtrado afectará al primero, y por lo tanto se evita que el destino de los paquetes pueda reensamblarlos por completo; sin embargo, se conocen fallos de programación que permiten poner fuera de combate máquinas simplemente enviándoles fragmentos. Usted elige.

Nota sobre las cabeceras: los paquetes malformados (los TCP, UDP e ICMP demasiado cortos como para que el código del cortafuegos pueda leer los puertos o el tipo y código de ICMP) son descartados cuando se intenta examinarlos. Lo mismo pasa con los fragmentos TCP que empiezan en la posición 8.

Por ejemplo, la siguiente regla descartará cualquier fragmento dirigido a 192.168.1.1:

# iptables -A OUTPUT -f -d 192.168.1.1 -j DROP
#

Extensiones a iptables: Nuevas coincidencias

iptables es extensible, lo que significa que se pueden extender tanto el núcleo como la herramienta iptables para proporcionar nuevas características.

Algunas de estas extensiones son estándar, y otras más exóticas. Las extensiones las puede hacer otra gente y pueden ser distribuidas por separado para diferentes nichos de usuarios.

Las extensiones al núcleo normalmente residen un directorio de módulos, como /lib/modules/2.3.15/net. Normalmente el núcleo los carga cuando son necesario, si fue compilado con la opción CONFIG_KMOD, de manear que no sería necesario cargarlos de forma manual.

Las extensiones al programa iptables son bibliotecas compartidas que residen normalmente en /usr/local/lib/iptables/, aunque una distribución podría ponerlas en /lib/iptables o /usr/lib/iptables.

Las extensiones son de dos tipos: nuevos objetivos (targets) y nuevas coincidencias (matches); hablaremos ahora sobre los nuevos objetivos. Algunos protocolos ofrecen de manera automática nuevos tipos de comprobaciones: en la actualidad son TCP, UDP e ICMP, como se muestra más adelante.

Para estos protocolos podrá especificar nuevas comprobaciones en la línea de órdenes tras la opción «-p», lo que cargará las extensiones. Para nuevas comprobaciones explícitas, use la opción «-m» para cargar las extensiones, tras lo cual estarán disponibles.

Para obtener ayuda sobre una extensión, use la opción que se usa para cargarla («-p», «-j» o «-m») seguida por «-h» o «--help», por ejemplo:

# iptables -p tcp --help
#

Extensiones TCP

Las extensiones TCP se cargan de forma automática si se especifica «-p tcp». Esto proporcionar las siguientes opciones (ninguna de las cuales se activa con fragmentos).

--tcp-flags

Seguido por una «!» opcional, y después dos cadenas de indicadores (flags), le permite filtrar dependiendo de ciertos indicadores de TCP. La primera cadena es la máscara: una lista de los indicadores que desea examinar. La segunda cadena indica cuales deben estar activos. Por ejemplo,

# iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DENY

Esto indica que deben ser examinados todos los indicadores («ALL» es sinónimo de «SYN,ACK,FIN,RST,URG,PSH»), pero sólo deben estar activos SYN y ACK. Hay otro argumento llamado «NONE», que significa «ningún indicador».

--syn

precedido de forma opcional por un «!», es equivalente a «--tcp-flags SYN,RST,ACK SYN».

--source-port

seguido de forma opcional por un «!», y después un puerto o rango de puertos TCP. Estos pueden estar representados por su nombre, tal como viene en /etc/services, o por número. Los rangos pueden ser dos nombres de puerto separados por un «-», un puerto seguido de un «-» (para especificar un puerto mayor o igual al indicado), o un puerto precedido de «-» (para especificar un puerto menor o igual al indicado).

--sport

sinónimo a «--source-port».

--destination-port

y

--dport

son lo mismo que lo anterior, sólo que especifican el puerto de destino, en lugar del de origen.

--tcp-option

seguido por un «!» (opcional) y un número, se ajusta a paquetes con una opción TCP igual a ese número. Un paquete que no tenga una cabecera TCP completa, será descartado automáticamente si se intenta examinar sus opciones TCP.

Explicación de los indicadores (flags) TCP

A veces es útil permitir conexiones TCP en una dirección, pero no en la otra. Por ejemplo, puede que queira permitir conexiones a un servidor WWW externo, pero no desde ese mismo servidor.

La solución del inexperto sería bloquear los paquetes TCP que vengan del servidor. Desafortunadamente, las conexiones TCP precisan que los paquetes fluyan en ambas direcciones para poder funcionar.

La solución es bloquear sólo los paquetes que se usan para solicitar una conexión. A éstos se les llama paquetes SYN (ok, técnicamente son paquetes con el indicador SYN activo, y los FIN y ACK inactivos, pero los llamamos paquetes SYN para abreviar). Rechazando estos paquetes, podemos detener intentos de conexión en su inicio.

El indicador (flag) «--syn» se usa para este propósito: sólo es válido para las reglas que especifican TCP como protocolo. Por ejemplo, para especificar intentos de conexión TCP desde 192.168.1.1:

-p TCP -s 192.168.1.1 --syn

Este indicador puede ser invertido precediéndolo con un «!», lo que significa cualquier paquete excepto el de inicio de conexión.

Extensiones UDP

Estas extensiones se cargan de forma automática si se especifica «-p udp». Proporciona las opciones «--source-port», «--sport», «--destination-port» y «--dport» con los mismos detalles que los indicados para TCP.

Extensiones ICMP

Esta extensión se carga de forma automática si se especifica «-p icmp». Proporciona sólo una opción nueva:

--icmp-type

seguida de un «!» opcional, y luego del nombre de un tipo icmp (p.ej. «host-unreachable»), un tipo numérico («3»), o un tipo numérico y un código separados por «/» («3/3»). Puede ver una lista de los nombres de los tipos icmp disponibles usando «-p icmp --help».

Otras extensiones de coincidencia (match)

Las otras extensiones del paquete netfilter son de demostración, que (si son instaladas) pueden ser invocadas con la opción «-m».

mac

Este módulo debe ser especificado de forma explícita con «-m mac» o «--match mac». Se usa para coincidencias en las direcciones Ethernet (MAC) de los paquetes entrantes, y por tanto sólo son útiles para los paquetes que pasan por las cadenas PREROUTING e INPUT. Proporciona sólo una opción:

--mac-source

seguida de un «!» opciona, y luego una dirección ethernet en notación hexadecimal separada por «:», por ejemplo «--mac-source 00:60:08:91:CC:B7».

limit

Este módulo debe ser especificado de forma explícita con «-m limit» o «--match limit». Se usa para restringir la tasa de coincidencias, como por ejemplo para suprimir mensajes de registro. Sólo se activará un número dado de veces por segundo (por defecto, 3 coincidencias por hora, a ráfagas de 5). Tiene dos argumentos opcionales:

--limit

seguido por un número; especifica el número máximo de coincidencias de media por segundo a permitir. El número puede especificar unidades de forma explícita, usando «/second», «/minute», «/hour», o «/day», o abreviadas (de manera que «5/second» es lo mismo que «5/s»).

--limit-burst

seguido de un número, indica la ráfaga más larga que se puede producir antes de comprobar el límite.

Este tipo de coincidencias se suele usar con el objetivo LOG para producir registros limitados por una tasa. Para comprender cómo funciona esto, veamos la siguiente regla, que registra los paquetes con los parámetros de limitación por defecto:

# iptables -A FORWARD -m limit -j LOG

La primera vez que se alcanza esta regla, se registra el paquete; en realidad, como la ráfaga por defecto es de 5, se registrarán los primeros cinco paquetes. Después, pasarán veinte minutos antes de que vuelva a registrarse un paquete con esta regla. Además, cada veinte minutos que pasen sin que un paquete alcance la regla, la ráfaga «recuperará» un paquete; si no sucede nada durante 100 minutos, la ráfaga quedará completamente «recargada»; de vuelta entonces a la situación inicial.

Ahora mismo no se pueden crear reglas con un tiempo de recarga mayor a 59 horas, de manera que si establece una tasa de recarga de un paquete por día, entonces el número de paquetes por ráfaga deberá ser menor que 3.

También puede usar este módulo para evitar varios ataques por denegación de servicio (DoS) con una tasa más rápida para incrementar la respuesta.

Protección contra Syn-flood (inundación mediante Syn):

# iptables -A FORWARD -p tcp --syn -m limit --limit 1/s -j ACCEPT

Furtivo buscando puertos (port scanner):

# iptables -A FORWARD -p tcp --tcp-flags SYN,ACK,FIN,RST RST -m limit --limit 1/s -j ACCEPT

Ping de la muerte:

# iptables -A FORWARD -p icmp --icmp-type echo-request -m limit --limit 1/s -j ACCEPT

Este módulo trabaja como una «puerta de histéresis», tal como se muestra en el gráfico siguiente.

           tasa (pkt/s)  
                 ^        .---.
                 |       / DoS \
                 |      /       \
Inicio del DoS-  |.....:.........\.......................
 = (limit *      |    /:          \
limit-burst)     |   / :           \         .-.
                 |  /  :            \       /   \
                 | /   :             \     /     \
Fin del DoS     -|/....:..............:.../.......\..../.
 = limit         |     :              :`-'         `--'
-----------------+-----+--------------+------------------> tiempo (s)
   LOGICA =>     Activa|   No activa  |    Activa

Digamos que las coincidencias son de un paquete por segundo, con una ráfaga de cinco paquetes, pero los paquetes comienzan a llegar a un ritmo de cuatro por segundo, durante tres segundos, y luego empezamos de nuevo con otros tres segundos.



         <--Flood 1-->           <---Flood 2--->

Paquetes^                 Máxima  __--      YNNN
Totales |               Tasa  __--      YNNN
        |             de  __--      YNNN
     10 |       Línea __--         Y
        |         __--            Y
        |     __--               Y
        | __--    YNNN           
        |-    YNNN
      5 |    Y    
        |   Y                           Leyenda:  Y -> Coincidencia
        |  Y                                      N -> No coincide
        | Y
        |Y 
      0 +--------------------------------------------------> Tiempo (seg.)
         0   1   2   3   4   5   6   7   8   9  10  11  12

Podemos ver que los primeros cinco paquetes tienen permiso para exceder la tasa de uno por segundo, y entonces entra en juego el límite. Si hay una pausa, entonces se permite otra ráfaga, pero no más allá de la tasa máxima establecida por la regla (un paquete por segundo después de «gastar» la ráfaga).

owner

Este módulo intenta ajustarse a varias características del creador del paquete, para aquellos generados de forma local. Sólo es válida para la cadena OUTPUT, e incluso algunos paquetes (como las respuestas a los paquetes ping) pueden no tener dueño, y por lo tanto nunca activar la regla.

--uid-owner idusuario

Coincide si el paquete fue creado por un proceso con el id efectivo de usuario dado (numérico).

--uid-owner idgrupo

Coincide si el paquete fue creado por un proceso con el id efectivo de grupo dado (numérico).

--pid-owner idproceso

Coincide si el paquete fue creado por un proceso con el id efectivo de proceso dado.

--sid-owner idproceso

Coincide si el paquete fue creado por un proceso perteneciente a la sesión de grupo dada.

unclean

Este módulo experimental debe ser especificado de forma explícita con «-m unclean» o «--match unclean». Hace varios controles de corrección sobre los paquetes. Este módulo no ha pasado una auditoría, y no debería ser usado como dispositivo de seguridad (posiblemente empeore las cosas, ya que podría tener fallos). No proporciona opciones.

La coincidencia (match) State

El criterio de coincidencia más útil vienen proporcionado por la extensión «state», que interpreta el análisis de seguimiento de conexión del módulo «ip_conntrack». Lo recomiendo encarecidamente.

Especificar «-m state» permite una opción «--state» adicional, que es una lista separada de estados a buscar (el indicador «!» especifica que no se desea buscar esos estados). Los estados son:

NEW

Paquete que crea una nueva conexión.

ESTABLISHED

Paquete que pertenece a una conexión existente (esto es, que tuvo paquetes de respuesta).

RELATED

Paquete que está relacionado a una conexión existente, pero que no es parte de ella, como un error ICMP o (con el módulo de FTP insertado), un paquete que establece una conexión de datos ftp.

INVALID

Paquete que no pudo ser identificado por alguna razón: incluye quedarse sin memoria y errores ICMP que no corresponden a ninguna conexión conocida. Normalmente estos paquetes deberían ser descartados.

7.4 Especificación de objetivos

Ahora que sabemos qué exámenes podemos hacer a un paquete, necesitamos una manera de decir qué hacer con los paquetes que se ajustan a nuestras pruebas. A esto se le denomina objetivo (target) de una regla.

Hay dos objetivos implementados en el sistema bastante sencillos: DROP y ACCEPT. Ya los hemos visto ambos. Si una regla coincide con un paquete, y su objetivo es alguno de estos dos, no se consultarán más reglas: la suerte del paquete ha sido decidida.

Hay dos tipos de objetivos aparte de los que ya vienen: extensiones y cadenas definidas por el usuario.

Cadenas definidas por el usuario

Una característica potente que iptables hereda de ipchains es la capacidad del usuario de crear nuevas cadenas, aparte de las tres que ya vienen implementadas (INPUT, FORWARD y OUTPUT). Por concención, las cadenas definidas por el usuario van en minúsculas para distinguirlas (describiremos cómo crear nuevas cadenas luego en Operaciones con una cadena entera).

Cuando un paquete coincide con una regla cuyo objetivo es una cadena definida por el usuario, el paquete empieza a atravesar esa otra cadena. Si en ella no se decide la suerte del paquete, una vez llegado el final de la cadena, se vuelve al mismo punto desde el que se saltó, a la siguiente regla de la antigua cadena.

Es el momento de un poco más de «ASCII art». Consideremos dos cadenas (bastante tontas): INPUT (la cadena interna) y prueba (una cadena definida por el usuario).

         `INPUT'                         `prueba'
        -----------------------------   -----------------------------
        | Regla1: -p ICMP -j DROP   |   | Regla1: -s 192.168.1.1    |
        |---------------------------|   |---------------------------|
        | Regla2: -p TCP -j prueba  |   | Regla2: -d 192.168.1.1    |
        |---------------------------|   -----------------------------
        | Regla3: -p UDP -j DROP    |
        -----------------------------

Consideremos un paquete TCP que venga de 192.168.1.1, y vaya a 1.2.3.4. Entra en la cadena INPUT, y pasa se compara con Regla1 (no coincide). Coincide con Regla2, y su objetivo es prueba, de manera que la siguiente regla que se examina es el comienzo de prueba. La Regla1 de prueba coincide, pero no especifica un objetivo, de manera que se examina la siguiente regla, Regla2. No coincide, de manera que hemos llegado al final de la cadena. Volvemos a INPUT, donde acabábamos de examinar Regla2, de manera que comprobamos Regla3, que tampoco coincide.

De manera que el camino que hace el paquete es:

                                v    __________________________
         `INPUT'                |   /    `prueba'              v
        ------------------------|--/    -----------------------|----
        | Regla1                | /|    | Regla1               |   |
        |-----------------------|/-|    |----------------------|---|
        | Regla2                /  |    | Regla2               |   |
        |--------------------------|    -----------------------v----
        | Regla3                /--+___________________________/
        ------------------------|---
                                v

Las cadenas definidas por el usuario pueden saltar a otras (pero no haga bucles, los paquetes serán descartados si se detecta que están en bucle).

Extensiones a iptables: Nuevos objetivos

El otro tipo de objetivo es una extensión. Una extensión de objetivo consiste en un módulo del núcleo, una extensión opcional a iptables para proporcionar nuevas opciones en línea de órdenes: Hay varias extensiones en la distribución de netfilter básica:

LOG

Este módulo proporciona un registro de paquetes coincidentes mediante el núcleo. Dispone de estas opciones adicionales:

--log-level

Seguido de un número (o nombre) de nivel. Los nombres válidos son (distingue mayúsculas/minúsculas) «debug», «info», «notice», «warning», «err», «crit», «alert», «emerg», que corresponden a los números 7 a 0. Vea la página de manual de syslog.conf si necesita una explicación de estos niveles.

--log-prefix

Seguido de una cadena de hasta 30 caracteres, que corresponden a un texto que se escribe al comienzo de cada «log» (registro), para permitir que sean identificados unívocamente.

Este módulo es más útil junto a un objetivo «limit», de manera que no se inunden los archivos de registro.

REJECT

Este módulo tiene el mismo efecto que «DROP», excepto que al remitente se le envía un mensaje de error ICMP «port unreachable». Fíjese que el mensaje de error ICMP no se envía si (vea el RFC 1122):

REJECT también admite un argumento opcional «--reject-with» que altera el paquete re respuesta a usar: vea la página de manual.

Objetivos especiales de serie

Hay dos objetivos especiales que vienen de serie: RETURN y QUEUE.

RETURN tiene el mismo efecto que si hubiésemos llegado al final de la cadena: si la regla estaba en una cadena de las que hay por defecto, entonces se ejecuta la política de la cadena. Para una regla que esté en una cadena definida por el usuario, se sale de ella, y se continúa atravesando la cadena anterior al salto, justo después de la regla con la que se saltó.

QUEUE es un objetivo especial, que pasa al paquete en una cola destinada al procesamiento en espacio de usuario. Para que esto sea útil, hacen falta otros dos componentes:

El controlador de cola estándar de iptables para IPv4 es el módulo ip_queue, que se distribuye con el núcleo y está marcado como experimental.

El que sigue es un ejemplo rápido de cómo usar iptables para poner en cola los paquetes para su proceso en espacio de usuario:

# modprobe iptable_filter
# modprobe ip_queue
# iptables -A OUTPUT -p icmp -j QUEUE
Con esta regla, los paquetes ICMP generados de forma local (como los que crea, digamos, ping), se pasan al módulo ip_queue, que entonces intenta pasarlos a una aplicación en espacio de usuario. Si no hay una aplicación esperando por ellos, entonces se descartan.

Para escribir una aplicación en espacio de usuario, utilice el API libipq. Se distribuye con iptables. Encontrará código de ejemplo en el conjunto de herramientas de pruebas (como redirect.c) en el CVS.

Se puede comprobar el estado de ip_queue mediante:

/proc/net/ip_queue
Se puede controlar la longitud máxima de la cola (número de paquetes entregados al espacio de usuario sin dictar veredicto) mediante:
/proc/sys/net/ipv4/ip_queue_maxlen
El valor por defecto para la longitud máxima de la cola es 1024. Una vez se alcance este límite, los paquetes nuevos serán descartados hasta que la longitud de la cola caiga por debajo del límite de nuevo. Los protocolos buenos como TCP interpretan a partir de los paquetes descartados que hay congestión en la red, y deberían reintentar cuando la cola se llene. Sin embargo, habrá que experimentar un poco para determinar una longitud máxima ideal para la cola para una situación dada si el valor por defecto es demasiado pequeño.

7.5 Operaciones con una cadena entera

Una característica bastante útil de iptables es la capacidad de agrupar reglas relacionadas en una cadena. Podemos poner el nombre que queramos a las cadenas, pero yo recomiendo usar letras minúsculas para evitar confundirlas con las cadenas y objetivos proporcionados por defecto. Los nombres de las cadenas pueden tener hasta 31 letras.

Crear una nueva cadena

Creemos una nueva cadena. Como soy una persona tan imaginativa, la llamaré prueba. Usaremos las opciones «-N» o «--new-chain»:

# iptables -N prueba
#

Es así de simple. Ahora podemos poner reglas en ella tal como se detalló anteriormente.

Borrar una cadena

Borrar una cadena es igualmente simple, y se utilizan las opciones «-X» o «--delete-chain». żPor qué «-X»? Bueno, todas las letras buenas estaban cogidas ya.

# iptables -X prueba
#

Hay un par de restricciones al borrar cadenas: deben estar vacías (vea Vaciar una cadena más adelante) y no pueden ser el objetivo de ninguna regla. Tampoco puede borrar ninguna de las tres cadenas del sistema.

Si no especifica una cadena, entonces serán borradas todas las cadenas definidas por el usuario, si es posible.

Vaciar una cadena

Hay una manera sencilla de eliminar todas las reglas de una cadena, usando la orden «-F» (o «--flush»).

# iptables -F forward
#

Si no especifica una cadena, todas serán vaciadas.

Listar el contenido de una cadena

Puede listar todas las reglas de una cadena usando la orden «-L» (o «--list»).

El «refcnt» mostrado para cada cadena definida por el usuario es el número de reglas que tienen esa cadena como objetivo. Deber ser cero (y la cadena estar vacía) antes de que la cadena pueda ser borrada.

Si se omite el nombre de la cadena, se muestran todas, incluso las vacías.

Hay tres opciones que pueden acompañar a «-L». La opción «-n» (numérico) es útil ya que evita que iptables intente averiguar el nombre de las direcciones IP, lo que (si está usando DNS como la mayoría de la gente) puede causar grandes retrasos si el DNS no está configurado adecuadamente, o está filtrando las consultas DNS. También hace que los puertos TCP y UDP aparezcan listados por número, en lugar de por nombre.

Las opciones «-v» muestran todos los detalles de las reglas, tales como los contadores de paquetes y bytes, las comparaciones TOS, y las interfaces. En cualquier otro caso, se omitirán estos valores.

Fíjese que los contadores de paquetes y bytes se muestran usando los sufijos «K», «M» o «G», indicando 1000, 1.000.000 y 1.000.000.000 respectivamente. Use el indicador «-x» (expandir números) para mostrar los números completos, sin importar lo grande que sean.

Restablecer (poner a cero) los contadores

Es útil poder poner a cero los contadores. Esto se puede hacer con la opción «-Z» (o «--zero»).

El problema de esta solución es que a veces necesitamos saber el valor del contador inmediatamente antes de ser restablecidos. En el ejemplo anterior, podría ser que algunos paquetes pasasen entre las órdenes «-L» y «-Z». Por esta razón, puede usar «-L» y «-Z» juntas, para poner a cero los contadores, al mismo tiempo que lee su contenido.

Establecer la política

Comentamos lo que sucede cuando un paquete llega al final de una cadena del sistema cuando discutimos antes cómo atraviesa el paquete las cadenas. En este caso, la política de la cadena determina la suerte del paquete. Sólo las cadenas del sistema (INPUT, OUTPUT y FORWARD) tienen políticas, porque si un paquete llega al final de una cadena definida por el usuario, se vuelve a la cadena anterior.

La política puede ser ACCEPT o DROP.


Página siguiente Página anterior Índice general