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:
Las reglas de una cadena se pueden manipular de varias maneras:
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.
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.
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:
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».
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.
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.
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).
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
#
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
#
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).
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».
precedido de forma opcional por un «!», es equivalente a «--tcp-flags SYN,RST,ACK SYN».
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).
sinónimo a «--source-port».
y
son lo mismo que lo anterior, sólo que especifican el puerto de destino, en lugar del de origen.
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.
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.
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.
Esta extensión se carga de forma automática si se especifica «-p icmp». Proporciona sólo una opción nueva:
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».
Las otras extensiones del paquete netfilter son de demostración, que (si son instaladas) pueden ser invocadas con la opción «-m».
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:
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».
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:
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»).
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).
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.
Coincide si el paquete fue creado por un proceso con el id efectivo de usuario dado (numérico).
Coincide si el paquete fue creado por un proceso con el id efectivo de grupo dado (numérico).
Coincide si el paquete fue creado por un proceso con el id efectivo de proceso dado.
Coincide si el paquete fue creado por un proceso perteneciente a la sesión de grupo dada.
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.
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:
Paquete que crea una nueva conexión.
Paquete que pertenece a una conexión existente (esto es, que tuvo paquetes de respuesta).
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.
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.
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.
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).
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:
Este módulo proporciona un registro de paquetes coincidentes mediante el núcleo. Dispone de estas opciones adicionales:
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.
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.
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.
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 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.
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.
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 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.
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.
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.
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.
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
.