En esta sección hablaremos sobre las comparaciones. He decidido agrupar las comparaciones en cinco categorías diferentes: para empezar tenemos las comparaciones genéricas, que pueden usarse en todas las reglas; a continuación vienen las comparaciones TCP que sólo pueden aplicarse a los paquetes TCP; después vienen las comparaciones UDP y las comparaciones ICMP, que sólo se aplican a paquetes UDP e ICMP respectivamente; por último queda un grupo de comparaciones especiales, como las de estado, las de propietario, comparaciones límite, etc. Este último grupo se ha clasificado en subcategorías, aunque en realidad no tienen por qué ser comparaciones diferentes. Espero que esta clasificación sea razonable y todo el mundo pueda entenderla.
Una comparación genérica es un tipo de comparación que está siempre disponible, sea cual sea el protocolo con el que trabajemos y sin importar qué extensiones de comparación se hayan cargado: no se necesitan parámetros especiales para emplearlas. He incluído aquí la comparación --protocol, aunque podría parecer más adecuado que estuviera en las comparaciones de protocolo. Por ejemplo, si queremos emplear una comparación TCP, necesitaremos usar la comparación --protocol con la opción TCP. Sin embargo --protocol también es una comparación por sí misma, ya que puede usarse para comparar protocolos específicos. Las siguientes comparaciones siempre están disponibles.
Table 6-4. Comparaciones genéricas
Comparación | -p, --protocol |
Ejemplo | iptables -A INPUT -p tcp |
Descripción | Esta comparación se emplea para comprobar la presencia de los siguientes protocolos: TCP, UDP, ICMP o sus respectivos valores numéricos, tal como se especifican en el archivo endterm="protocolstxt.title>. Si no puede identificar uno de éllos devolverá un error. El protocolo puede corresponder a uno de los tres mencionados, aunque también puede corresponder a TODOS (ALL). "ALL" significa que se corresponde con todos los protocolos (TCP, UDP e ICMP). El comando también acepta listas de protocolos delimitados por comas, por ej. udp,tcp que buscaría paquetes UDP y TCP. Si a esta comparación se le especifica el valor cero (0) será como si se especificaran TODOS (ALL) los protocolos (éste es el valor por defecto si no se usa la comparación --protocol). También se puede invertir la comparación con el símbolo !; o sea que --protocol ! tcp quiere decir que se tienen que comparar todos los protocolos excepto el TCP (o sea, UDP e ICMP). |
Comparación | -s, --src, --source |
Ejemplo | iptables -A INPUT -s 192.168.1.1 |
Descripción | Esta es la comparación del origen, que se basa en la dirección IP de origen de los paquetes. El uso genérico compara direcciones IP únicas, como 192.168.1.1. Sin embargo también acepta máscaras de red en un formato de "bit" CIDR, especificando el número de unos (1) en la parte izquierda de la máscara de red: cada número es el equivalente decimal de un número binario de 8 bits, en el que la combinación de "1"s y "0"s en cadenas de ocho números, equivale a un valor decimal; por ej., 8 unos seguidos en binario equivalen a 255 y si tenemos "8 unos, punto, 8 unos, punto, 8 unos, punto, 8 ceros", en notación decimal, la que todos gastamos, tenemos "255.255.255.0". Ésto significa que podemos indicar /24 (tres veces ocho, sumados) para emplear una máscara de red 255.255.255.0. Así podemos comparar rangos completos de direcciones IP, como nuestras redes locales o segmentos de red tras un cortafuegos, especificándolo más o menos así: 192.168.0.0/24 (con ello se buscarían paquetes que cayeran dentro del rango 192.168.0.1- 192.168.0.254). Otra forma de hacerlo es con una máscara de red tradicional: 255.255.255.255 (es decir, 192.168.0.0/255.255.255.0). También se puede invertir la comparación escribiendo el símbolo !: si empleamos una comparación como --source ! 192.168.0.0/24, lo que conseguiremos es comparar todos los paquetes que NO provengan del rango 192.168.0.x. Por defecto se comparan todas las direcciones. |
Comparación | -d, --dst, --destination |
Ejemplo | iptables -A INPUT -d 192.168.1.1 |
Descripción | La comparación --destination (destino) se usa en función de la dirección/direcciones de destino de los paquetes. Se emplea casi igual que la comparación --source y tiene la misma sintaxis, excepto que se basa en saber a dónde se dirijen los paquetes. Para comparar un rango de direcciones IP, podemos especificar una máscara de forma "ortodoxa" o indicando el número de unos (1) contados desde la parte izquierda de la máscara de red (como en --source, la notación CIDR se basa en números binarios, formados con ristras de unos y ceros que equivalen a números decimales). Por ej.: 192.168.0.0/255.255.255.0 y 192.168.0.0/24 son equivalentes. También se puede invertir la comparación con el símbolo !, o sea que --destination ! 192.168.0.1 buscará todos los paquetes que no vayan destinados a la dirección IP 192.168.0.1. |
Comparación | -i, --in-interface |
Ejemplo | iptables -A INPUT -i eth0 |
Descripción | Esta comparación la emplearemos para reconocer a través de qué interfaz proviene un paquete entrante. Esta opción sólo es válida en las cadenas INPUT, FORWARD y PREROUTING, devolviendo un error si se usa en cualquier otro sitio. Si no especificamos una interfaz concreta, por defecto se asume el valor +, que se emplea para comparar una cadena de letras y números; o sea que por defecto el núcleo comparará todos los paquetes sin importarle a través de qué interfaz vienen. El símbolo + también puede añadirse al tipo de interfaz, de forma que eth+ revisará los paquetes que entren por cualquier tarjeta de red Ethernet. También es posible invertir el significado de esta opción con ayuda del símbolo !. La línea tendrá una sintaxis parecida a: -i ! eth0, que aceptará los paquetes de todas las interfaces Ethernet por donde llegan datos, excepto la interfaz eth0. |
Comparación | -o, --out-interface |
Ejemplo | iptables -A FORWARD -o eth0 |
Explicación | Esta comparación se emplea con los paquetes que están a punto de abandonar la interfaz de salida. Ten en cuenta que esta comparación sólo está disponible en las cadenas OUTPUT, FORWARD y POSTROUTING, de hecho son justo las opuestas a las de la comparación --in-interface. Aparte de ésto, ambas funcionan prácticamente igual. La extensión + implica comparar todas las tarjetas del mismo tipo, es decir eth+ controlará todas las tarjetas eth y de forma similar los demás casos. Para invertir el significado de la comparación puedes usar el símbolo ! de la misma forma que en --in-interface. Si no se especifica ninguna comparación --out-interface, por defecto se comparan todas las tarjetas, independientemente de dónde vaya el paquete. |
Comparación | -f, --fragment |
Ejemplo | iptables -A INPUT -f |
Descripción | Esta comparación se emplea para chequear la segunda y la tercera partes de un paquete fragmentado. La razón de ello es que cuando existen paquetes fragmentados no hay manera de saber ni las direcciones de origen/destino de los paquetes, ni los tipos ICMP, ni otros tantos detalles necesarios. Además los paquetes fragmentados pueden emplearse en ciertos casos como armas de ataque contra otros ordenadores. Fragmentos de paquetes como éstos no serán chequeados por otras reglas y por éllo se ha creado esta comparación. Como viene siendo habitual, esta opción puede combinarse con el símbolo !; sin embargo en este caso el símbolo debe preceder a la comparación, es decir ! -f. Cuando esta comparación se invierte, se comparan sólo las cabeceras de los paquetes y/o los paquetes no fragmentados. O lo que es lo mismo, en cualquier paquete fragmentado se comparará el primer fragmento, pero no el segundo, ni el tercero, ... Asímismo se comparará cualquier paquete no fragmentado durante la transmisión. Recuerda que siempre puedes usar las muy buenas opciones de defragmentación que hay en el núcleo. Por otra parte, si usas el seguimiento de conexiones te darás cuenta que no aparece ningún paquete fragmentado, puesto que se procesan los fragmentos antes de que lleguen a cualquier tabla o cadena de iptables. |
Esta sección describe las comparaciones que se cargan implícitamente, o sea, de forma totalmente automática, como por ejemplo cuando se compara --protocol tcp sin ningún criterio añadido. Actualmente hay tres grupos de comparaciones implícitas, uno para cada uno de los tres protocolos principales. Son las comparaciones TCP, comparaciones UDP y comparaciones ICMP. El grupo de comparaciones basadas en TCP contiene un conjunto de criterios singulares que sólo están disponibles para los paquetes TCP. De la misma manera actúan los criterios de los grupos para UDP e ICMP. Por otra parte, pueden haber comparaciones explícitas que se carguen cuando se les indica (explícitamente) y lógicamente estas comparaciones no son automáticas, si no que debes especificarlas correctamente. Para ésto deberás emplear la opción -m o --match, que explicaré más adelante.
Estas comparaciones son específicas del protocolo y sólo están disponibles al trabajar con paquetes y flujos TCP. Para emplearlas debes indicar --protocol tcp en la línea de comandos antes de empezar a utilizarlas. Por ello --protocol tcp debe estar a la izquierda de las comparaciones específicas del protocolo. Como ya se ha dicho, estas comparaciones se cargan automáticamente.
Table 6-5. Comparaciones TCP
Comparación | --sport, --source-port |
Ejemplo | iptables -A INPUT -p tcp --sport 22 |
Descripción | Esta comparación se emplea para comparar paquetes basándose en su dirección de origen. Si no se indica nada se comparan todos los puertos origen. La comparación puede tener un nombre de servicio o bien el número de un puerto. Si especificas un nombre de servicio, éste debe existir en el fichero /etc/services, puesto que iptables emplea este archivo para interpretar los nombres de los servicios. Si especificas el puerto por su número, la regla se cargará ligeramente más rápido, ya que iptables no tiene que buscar el nombre de servicio. Sin embargo, la comparación puede llegar a ser un poco más difícil de leer que si emplearas el nombre del servicio. Si estás escribiendo un conjunto de reglas de 200 ó más reglas, ciertamente deberías usar números de puerto, puesto que la diferencia es realmente notable (en una máquina lenta, esto puede significar hasta 10 segundos de diferencia si has configurado un conjunto de unas 1000 reglas). También puedes usar la comparación --source-port para comparar cualquier rango de puertos, como por ej. --source-port 22:80, en que se compararán los paquetes que provengan de los puertos 22 a 80. Si se omite el primer puerto del rango, se asume que quieres empezar por el 0 (es una opción implícita), o sea que --source-port :80 buscará paquetes que provengan de los puertos 0 a 80. Y de la misma forma, si el último puerto es el que se omite, implícitamente se está designando el puerto 65535; así, --source-port 22: implicará buscar paquetes que provengan de cualquier puerto entre el 22 y el 65535. Si inviertes el orden de los puertos, si no los especificas de menor a mayor, iptables interpreta automáticamente el rango "correcto": si escribes --source-port 80:22, iptables interpretará --source-port 22:80. Por ello, si por algún motivo lo que realmente deseas es el rango desde el puerto 80 hasta el 65535 y desde el 0 al 22 (lo que puede entenderse por 80:22), debes hacer uso del símbolo !, con lo que escribirás --source-port ! 23:79. Date cuenta que a primera vista la única diferencia es el símbolo de exclamación, pero el significado varía mucho (en este caso se ignoran todos los puertos entre el 23 y el 79, como deseábamos). Asímismo con --source-port ! 22 se compararán todos los paquetes excepto aquellos que provengan del puerto 22. Debes saber también que esta comparación no acepta puertos múltiples o rangos de puertos múltiples separados por comas. Para mayor información sobre este tema, léete la extensión de comparación multipuerto. |
Comparación | --dport, --destination-port |
Ejemplo | iptables -A INPUT -p tcp --dport 22 |
Descripción | Esta comparación busca paquetes TCP basándose en el puerto de destino. Utiliza la misma sintaxis que la comparación --source-port, por lo que acepta puertos, rangos de puertos e inversiones. También "corrije" el orden de los rangos de puertos (80:22 se leerá 22:80) y se asumen los valores 0 y 65535 en caso de no indicar el primer o el último puerto, respectivamente (:80 y 22: , respectivamente). Esta comparación tampoco acepta puertos o rangos múltiples separados por comas (para eso está la extensión de comparación multipuerto). |
Comparación | --tcp-flags |
Ejemplo | iptables -p tcp --tcp-flags SYN,FIN,ACK SYN |
Descripción | Esta comparación busca en las banderas (flags) de los paquetes TCP. Para empezar la comparación lee una lista de banderas para comparar (una máscara) y después lee una lista de banderas que deben estar establecidas con el valor 1, o sea estar activadas. Ambas listas deben estar delimitadas por comas. La comparación reconoce las banderas SYN, ACK, FIN, RST, URG y PSH, además de interpretar las palabras ALL (todas) y NONE (ninguna). ALL y NONE casi no necesitan explicación: ALL significa que se deben emplear todas las banderas, mientras que NONE significa no usar ninguna bandera para la comparación. De aquí que --tcp-flags ALL NONE signifique que se deben chequear todas las banderas TCP y comprobar si ninguna de ellas está activada. Esta opción también puede ser invertida por el símbolo !, es decir, si se especifica ! SYN,FIN,ACK SYN, lo que se obtiene es una comparación que busque todos los paquetes que tengan activados los bits ACK y FIN, pero no el bit SYN: la máscara de búsqueda incluye las banderas SYN, FIN y ACK, por lo que se chequearán sólo estas banderas; entonces, si fuera una búsqueda directa, se determinaría si la bandera SYN está activada, al contrario que las FIN y ACK, que al no incluirse en la segunda lista deberían estar desactivadas; sin embargo, al ser una comparación invertida se buscará que FIN y ACK sí estén activadas y que SYN no esté activada. Date cuenta también que las comas no deben incluir espacios (puedes ver la sintaxis correcta en el ejemplo de arriba). |
Comparación | --syn |
Ejemplo | iptables -p tcp --syn |
Descripción | Se puede decir que la comparación --syn es una reliquia de los días de ipchains y que permanece para garantizar la compatibilidad con viejas reglas y para facilitar la transición de ipchains a iptables. Se usa para comparar paquetes que tengan activado el bit SYN y que no tengan activados los bits ACK y RST. Es decir, hace lo mismo que la comparación --tcp-flags SYN,RST,ACK SYN. Estos paquetes se emplean principalmente para solicitar nuevas conexiones a un servidor. Si bloqueas estos paquetes lo que consigues en la práctica es bloquear cualquier intento de conexión desde el exterior. Sin embargo, no habrás bloqueado las conexiones hacia el exterior y este fallo es el que explotan muchos ataques de hoy en día (por ej., "hackear"/romper la integridad y seguridad de un servicio legítimo y a partir de ahí instalar un programa o ejecutable similar que permita iniciar una conexión existente hacia tu host, en lugar de abrir un nuevo puerto en el host). Esta comparación también puede ser invertida con el sígno de exclamación (!) de esta forma: ! --syn. Ésto hace que se reconozcan los paquetes con los bits RST o ACK activados, o sea, los paquetes de una conexión ya establecida. |
Comparación | --tcp-option |
Ejemplo | iptables -p tcp --tcp-option 16 |
Descripción | Esta comparación se emplea para filtrar paquetes dependiendo de sus opciones TCP. Una Opción TCP (TCP Option) es una parte específica de la cabecera de cada paquete que consta de 3 campos diferentes. El primero tiene un tamaño de 8 bits y nos dice qué Opciones se emplean en el flujo. El segundo también es de 8 bits y nos dice qué tamaño tiene el campo de opciones. La razón para que exista este campo indicando el tamaño es que las Opciones TCP son, valga la redundancia, opcionales. Para seguir los estándares no necesitamos implementar todas las opciones, sinó que simplemente podemos mirar qué tipo de opción es y si la soportamos, puesto que de no soportarla miraremos cuál es el tamaño del campo y entonces ignoraremos esta parte de los datos del paquete. Esta comparación se emplea para buscar diferentes opciones TCP dependiendo de sus valores decimales. También puede ser invertido con !, de forma que la comparación busque todas las opciones pero ignore la opción indicada. Para ver una lista completa con todas las opciones échale un vistazo a Internet Engineering Task Force, que mantiene una lista de todos los números estándar empleados en Internet. |
Esta sección describe las comparaciones que sólo trabajarán con paquetes UDP. En cuanto especificas la comparación --protocol UDP, las opciones se cargan implícitamente (sin que haga falta indicarlas) y automáticamente ya están disponibles. Recuerda que los paquetes UDP no están orientados a la conexión y por éllo no existen banderas para establecer su valor en el paquete de forma que indiquen cuál es la utilidad del datagrama (como abrir o cerrar una conexión) o si únicamente sirven para enviar datos. Asímismo, tampoco requieren ningún tipo de reconocimiento: si se pierden, simplemente se han perdido (si no tenemos en cuenta los mensajes de error ICMP). Ésto significa que hay muchas menos comparaciones con las que trabajar en paquetes UDP, comparados con los paquetes TCP. Cabe destacar que la máquina de estados trabaja con todo tipo de paquetes, a pesar de que los paquetes UDP e ICMP se entienden como protocolos sin conexión. Más aún, la máquina de estados trabaja prácticamente igual con los paquetes UDP que con los TCP.
Table 6-6. Comparaciones UDP
Comparación | --sport, --source-port |
Ejemplo | iptables -A INPUT -p udp --sport 53 |
Descripción | Esta comparación trabaja exactamente igual que su homónima en TCP y se emplea para hacer comparaciones basadas en los puertos UDP de origen. Acepta rangos de puertos, puertos únicos e inversiones, con la misma sintaxis que lo hace la homónima en TCP: para especificar un rango indicarás el puerto inicial y el final (por ej. 22:80), con lo cual se compararán los puertos UDP incluídos entre ambos (desde el 22 hasta el 80, en el ejemplo); si el valor inicial se omite se asumirá el valor 0; si se omite el puerto final, se asume el puerto 65535; si el puerto con valor más alto se indica antes que el puerto con valor más bajo, iptables entenderá el rango inverso (si se escribe 80:22, se entiende 22:80). Las comparaciones con un único puerto UDP serán similares al ejemplo inicial. Para invertir la selección de puertos, añade el símbolo de exclamación !, como en --source-port ! 53 (con ello se compararán todos los puertos excepto el 53). La comparación puede interpretar nombres de servicios, siempre que estén disponibles en el archivo /etc/services. Sin embargo, no se aceptan puertos múltiples ni rangos múltiples separados por comas. Para más información sobre este tema léete la extensión de comparaciones multipuerto. |
Comparación | --dport, --destination-port |
Ejemplo | iptables -A INPUT -p udp --dport 53 |
Descripción | Podemos decir lo mismo en ésta y en la comparación anterior. Es exactamente lo mismo que su homónima en TCP, a excepción que aquí se comparan puertos UDP: compara paquetes basados en su puerto UDP de destino. Acepta rangos de puertos, puertos únicos e inversiones. Para reconocer un sólo puerto, usarás por ej. --destination-port 53; en cambio, para invertir la selección usarás --destination-port ! 53. En el primer caso la comparación buscará todos los paquetes dirigidos al puerto 53, mientras que en el segundo caso (el invertido) se buscarán todos los paquetes excepto los dirigidos al puerto 53. En el caso de un rango de puertos, puedes escribir --destination-port 8:19, con lo cual se captarán todos los paquetes dirigidos a los puertos comprendidos entre el 8 y el 19. Si se omite el primer puerto, se asume el valor 0. Si por el contrario se omite el segundo, se asumirá el valor 65535. Si se invierte el orden de los puertos (19:8), el programa los reordena automáticamente (se convierte en 8:19). Esta comparación no admite puertos y rangos múltiples (para ello existe la extensión de comparación multipuerto). |
Los paquetes ICMP son incluso más efímeros, tienen una vida más corta, que los paquetes UDP, dado que no están orientados a la conexión. El protocolo ICMP se usa principalmente para comunicación de errores, control de conexiones y tareas similares. ICMP no es un protocolo subordinado al protocolo IP, sinó más bien un protocolo que mejora al protocolo IP y le ayuda a gestionar los errores. Las cabeceras de los paquetes ICMP son muy similares a las cabeceras IP, pero presentan varias diferencias. La principal característica de este protocolo es la cabecera de "tipo", la cual nos indica para qué es el paquete. Por ejemplo, si intentamos acceder a una dirección IP inaccesible, normalmente recibiremos un ICMP host unreachable (mensaje ICMP de host inalcanzable) como respuesta. Para ver una lista completa de los "tipos" ICMP, lee el apéndice Tipos ICMP. Sólo hay una comparación específica para paquetes ICMP y es de esperar que sea suficiente con élla. Esta comparación se carga implícitamente al emplear la comparación --protocol ICMP y tenemos acceso a ella automáticamente. Recuerda que todas las comparaciones genéricas se pueden usar con ella, por lo que nos podemos centrar en las direcciones de origen y destino.
Table 6-7. Comparaciones ICMP
Comparación | --icmp-type |
Ejemplo | iptables -A INPUT -p icmp --icmp-type 8 |
Descripción | Esta comparación se usa para especificar el tipo ICMP a comparar. Los tipos ICMP se pueden especificar por su valor numérico o por su nombre. Los valores numéricos están definidos en el RFC 792. Para obtener un listado completo de los nombres ICMP, ejecuta iptables --protocol icmp --help en la línea de comandos o mira en el apéndice Tipos ICMP. Esta comparación también puede ser invertida con el símbolo !, como en --icmp-type ! 8. Ten en cuenta que algunos tipos ICMP están obsoletos, mientras que otros pueden ser "peligrosos" para un host desprotegido, puesto que pueden (entre otras cosas) redirigir paquetes a lugares incorrectos. |
Las comparaciones explícitas son aquellas que se deben cargar específicamente con la opción -m o --match. Por ej., las comparaciones de estado exigen añadir la directiva -m state antes de introducir la comparación que deseas usar. Algunas de estas comparaciones pueden ser específicas de un protocolo. Otras pueden ser independientes de los protocolos, como las de los estados de conexión: NEW (NUEVO; el primer paquete de una conexión que todavía no está establecida), ESTABLISHED (ESTABLECIDO; una conexión que ya está registrada en el núcleo), RELATED (RELACIONADO; una nueva conexión que ha sido creada por otra conexión ya establecida y más antigua), etc. Existen unas cuantas, por otra parte, que pueden haber evolucionado con propósitos experimentales o de prueba, o simplemente para mostrar de qué es capaz iptables. Ésto significa que no todas estas comparaciones tienen una aplicación directa o "útil" a primera vista. Sin embargo es perfectamente posible que en tu caso concreto encuentres utilidad a alguna comparación específica. Además, cada vez hay más con cada nueva versión de iptables y que les encuentres utilidad dependerá en gran medida de tu imaginación y tus necesidades. La diferencia entre comparaciones cargadas implícita o explícitamente es que las implícitas se cargarán automáticamente cuando, por ej., compares las propiedades de los paquetes TCP, mientras que las explícitas nunca se cargarán automáticamente: es tarea enteramente tuya que descubras y actives las comparaciones explícitas.
La comparación limit (límite o limitación) debe ser cargada de forma explícita mediante la opción -m limit. Como ejemplo típico, esta comparación puede usarse para limitar el registro de actividad de reglas específicas. Ésto es, puedes comprobar que los paquetes no hayan excedido un determinado valor, a partir del cual se limita el registro de ese evento en cuestión. Imagina un límite de tiempo: puedes limitar las veces que una regla puede ser alcanzada en un periodo de tiempo dado, como cuando quieres minimizar los efectos de un "ataque de denegación de servicio por desbordamiento" (DoS). Éste es su principal uso, pero hay más, por supuesto. La comparación también puede ser invertida escribiendo el símbolo ! antes de la comparación límite: -m limit ! --limit 5/s, que quiere decir que todos los paquetes se compararán después de sobrepasar el límite de 5 veces por segundo.
Para ampliar la explicación, se puede decir que es básicamente como un "monedero virtual". Consideremos un monedero del que sacamos X monedas para gastar y al que introducimos monedas cada cierto tiempo. X se define dependiendo de cuántos paquetes recibimos que concuerdan con la comparación, por lo que suponiendo que son 3 paquetes, sacaremos del monedero 3 monedas en esa unidad de tiempo. La opción --limit nos dice con cuántos paquetes (monedas) rellenaremos el monedero por unidad de tiempo, mientras que --limit-burst indica la cantidad de monedas iniciales del monedero, así como cuántas de esas monedas admite el monedero. Así pues, escribiendo --limit 3/minute --limit-burst 5, crearemos un "monedero" con 5 "monedas"; si recibimos a continuación 5 paquetes seguidos que concuerden con la comparación, como resultado el "monedero" se vaciará. Tras 20 segundos, el "monedero" se rellena con otra "moneda" (recordemos que se rellena a razón de 3 por minuto) y a ese ritmo seguirá "rellenándose" hasta que se alcance el tope impuesto por el --limit-burst o hasta que sean usadas y el "monedero" vuelva a estar vacío.
Vamos a ver otro ejemplo algo más realista para aclarar mejor el funcionamiento:
Creamos una regla que contenga la siguiente comparación: -m limit --limit 5/second --limit-burst 10/second. El contador se establece con un valor inicial de 10. Cada paquete que coincida con el filtro de la regla resta una unidad al contador.
Recibimos una serie de paquetes (1-2-3-4-5-6-7-8-9-10) que coinciden con la regla, todos éllos en 1/1000 de segundo.
Ahora el contador está a cero ("vacío") y los paquetes que coincidan con la regla no serán filtrados por ésta y saltarán a la siguiente regla si existe, o en caso de no existir seguirán la política por defecto de la cadena.
Por cada 1/5 de segundo sin paquetes que coincidan, el contador aumenta una unidad hasta el valor máximo de 10. 1 segundo después de haber recibido los 10 paquetes anteriores, volveremos a aceptar hasta 5 paquetes seguidos.
Y por supuesto, el contador irá descontando 1 unidad por cada paquete correcto que se reciba.
Table 6-8. Opciones de comparación límite
Comparación | --limit |
Ejemplo | iptables -A INPUT -m limit --limit 3/hour |
Descripción | Mediante esta opción se establece el valor más alto del ratio medio de comparaciones positivas para la comparación limit. Se especifica mediante un valor numérico y un valor opcional de medida del tiempo. Las unidades de tiempo aceptadas actualmente son: /second (segundo), /minute (minuto), /hour (hora) y /day (día). El valor por defecto es de 3 cada hora, o lo que es lo mismo 3/hour. Así pues, con esta opción se consigue indicar a limit cuántas veces se le permite actuar a la comparación por unidad de tiempo (por cada minuto, por ej.). |
Comparación | --limit-burst |
Ejemplo | iptables -A INPUT -m limit --limit-burst 5 |
Descripción | Mediante esta opción le dices a iptables el número máximo de paquetes que concuerden con la comparación en un tiempo determinado. Este número (la cantidad de paquetes que han llegado a la comparación) disminuye en una unidad por cada unidad de tiempo (definida por la opción --limit) en que el evento no se presenta (no llega ningún paquete), hasta llegar al valor mínimo (1). Si se repite el evento (empiezan a llegar paquetes), el contador se va incrementando hasta que llega al tope establecido por --limit-burst, para volver a empezar (si no llegan paquetes el contador disminuye, mientras que cuando van llegando aumenta hasta el umbral definido por --limit-burst). El valor por defecto es 5. La manera más simple de comprobar cómo funciona esta opción es utilizando el ejemplo Limit-match.txt. Con él podrás comprobar por tí mismo cómo funciona simplemente enviando pings a diferentes intervalos de tiempo y con diferentes valores tope. Todas las respuestas de eco (echo replies) serán bloqueadas hasta que se vuelva a alcanzar el umbral límite. |
La comparación MAC (Ethernet Media Access Control, o control de acceso a tarjetas Ethernet) se usa para comparar paquetes en función de su dirección MAC de origen [MAC source address; ésta es la dirección física de la tarjeta de red Ethernet: se trata de un código registrado en el hardware de la tarjeta que la hace única frente a todas las demás tarjetas fabricadas y por fabricar, es decir, no debería haber dos tarjetas Ethernet con la misma dirección MAC]. Por ahora esta comparación está un poco limitada, aunque en el futuro es posible que evolucione y sea más útil. Insistamos un poco: esta comparación SÓLO compara paquetes en función de su dirección MAC de ORIGEN.
Ten en cuenta que para usar este módulo lo cargamos explícitamente con la opción -m mac. Y digo ésto porque mucha gente se pregunta si la opción correcta no debería ser -m mac-source, pero no es el caso. |
Table 6-9. Opciones de la comparación MAC
Comparación | --mac-source |
Ejemplo | iptables -A INPUT -m mac --mac-source 00:00:00:00:00:01 |
Descripción | Como ya se ha dicho, esta comparación se emplea para buscar paquetes basándose en su dirección MAC de origen. La dirección MAC indicada debe tener el siguiente aspecto: XX:XX:XX:XX:XX:XX, pues de lo contrario no sería correcta (el programa la consideraría una dirección "ilegal"). La comparación también puede ser invertida con !, y se parecerá a --mac-source ! 00:00:00:00:00:01. En este ejemplo se aceptarán todos los paquetes excepto aquellos que provengan de la tarjeta Ethernet especificada (la que tenga la dirección MAC 00:00:00:00:00:01). Ten en cuenta que las direcciones MAC sólo se emplean en las redes de tipo Ethernet, por lo que sólo será viable emplear la comparación con tarjetas Ethernet. Además, sólo será válida en las cadenas PREROUTING, FORWARD e INPUT y en ninguna más. |
Esta extensión se emplea para comparar paquetes basándose en las marcas que tengan establecidas. Una marca (mark) es un campo especial mantenido por el núcleo, que se asocia a los paquetes mientras viajan por el ordenador. Las marcas pueden usarse por diferentes rutinas del núcleo para tareas como la configuración y el filtrado del tráfico. Hoy por hoy sólo existe una manera de establecer una marca en Linux y ésta es mediante el objetivo MARK en iptables. Anteriormente se establecía con el objetivo FWMARK de ipchains y por éllo hay gente que todavía se refiere a FWMARK en tareas avanzadas de enrutado. El campo "marca" se establece mediante un número entero positivo de entre los 4.294.967.296 valores posibles en un entorno de 32 bits. O sea, que es más bien difícil que puedas verte limitado por este valor durante bastante tiempo.
Table 6-10. Opciones de la comparación de marca
Comparación | --mark |
Ejemplo | iptables -t mangle -A INPUT -m mark --mark 1 |
Descripción | Empleamos la comparación para buscar paquetes que hayan sido marcados con anterioridad. Las marcas pueden establecerse gracias al objetivo MARK, que será tratado en la próxima sección. Todos los paquetes que atraviesan Netfilter reciben un campo de marca (mark field) especial y se asocian a él. Cabe destacar que este "mark field" no se propaga ni dentro ni fuera del paquete, sinó que permanece en el ordenador que lo creó. Si el campo marca coincide con la marca, entonces hay concordancia. El campo marca es un número entero positivo, por lo que pueden haber un máximo de 4.294.967.296 marcas diferentes (en entornos de 32 bits). También puedes utilizar una máscara en la marca, con lo cual su aspecto se podrá parecer a --mark 1/1. Si se especifica la máscara se efectuará una suma lógica (AND) con la marca especificada antes de ejecutar la comparación. |
La extensión multiport se emplea para especificar puertos múltiples y rangos de puertos múltiples. Si no tuviéramos la funcionalidad de esta comparación, necesitaríamos escribir múltiples reglas del mismo tipo simplemente para comparar diferentes puertos no contiguos (que no se pueden especificar mediante un rango).
No puedes emplear la comparación estándar de puertos junto a la comparación múltiple de puertos en la misma regla; por ej., no puedes escribir: --sport 1024:63353 -m multiport --dport 21,23,80, puesto que simplemente no funcionarán las dos a la vez, sinó que iptables ejecutará el primer elemento de la regla e ignorará el otro (en este caso ignorará la comparación multipuerto). |
Table 6-11. Opciones de comparación multipuerto
Comparación | --source-port |
Ejemplo | iptables -A INPUT -p tcp -m multiport --source-port 22,53,80,110 |
Descripción | Mediante esta comparación se buscarán los puertos de origen indicados, que serán como máximo 15. Los puertos se delimitarán mediante comas, como en el ejemplo. La comparación sólo se puede emplear conjuntamente con las comparaciones -p tcp o -p udp. Básicamente es una versión ampliada de la comparación estándar --source-port. |
Comparación | --destination-port |
Ejemplo | iptables -A INPUT -p tcp -m multiport --destination-port 22,53,80,110 |
Descripción | De la misma forma que la anterior, se comparan puertos múltiples, aunque esta vez son los puertos de destino de los paquetes. También presenta el límite de una lista con un máximo de 15 puertos y sólo puede utilizarse junto a -p tcp o -p udp. |
Comparación | --port |
Ejemplo | iptables -A INPUT -p tcp -m multiport --port 22,53,80,110 |
Descripción | Esta extensión puede emplearse para comparar paquetes basándose en su puerto de origen/destino. Funciona igual que las dos anteriores, con las mismas limitaciones, pero con la diferencia de que sólo se aceptarán paquetes que provengan y se destinen al mismo puerto; en el ejemplo estaríamos hablando de paquetes que provengan del puerto 22 y vayan al puerto 22, provengan del 53 y vayan al 53, etc. |
La extensión owner se emplea para comparar paquetes en función de la identidad del proceso que los creó. Se puede especificar como la identificación (ID) del proceso del usuario que ejecutó la orden en cuestión; este usuario puede ser el grupo, el proceso, la sesión o el comando en sí mismo. Esta extensión se creó originalmente para demostrar de qué es capaz iptables. La comparación owner sólo funciona en la cadena OUTPUT por razones obvias: es prácticamente imposible encontrar alguna información sobre la identidad del proceso que envió el paquete desde el otro extremo y menos aún si existe algún punto intermedio entre el origen y el destino. Incluso en la cadena OUTPUT no tiene un comportamiento muy fiable, pues ciertos paquetes pueden no tener un propietario (como ocurre por ejemplo con las diferentes respuestas ICMP, ya que éstas nunca serán aceptadas por la comparación).
Table 6-12. Opciones de comparación de propietario
Comparación | --uid-owner |
Ejemplo | iptables -A OUTPUT -m owner --uid-owner 500 |
Descripción | En esta comparación se aceptarán todos los paquetes que hayan sido generados por el usuario especificado (en inglés se habla de User ID o UID, siendo 500 la ID del ejemplo). Así pues, con esta regla podemos filtrar paquetes dependiendo del usuario que los haya creado. Una utilidad podría ser bloquear cualquier intento de abrir una conexión fuera del cortafuegos, siempre que el usuario no sea el administrador ("superuser", "su" o "root"). Otro posible uso sería bloquear a cualquier usuario que intente enviar paquetes por el puerto HTTP excepto al usuario http (con lo que minimizamos los ataques de troyanos que trabajen a través de ese puerto). |
Comparación | --gid-owner |
Ejemplo | iptables -A OUTPUT -m owner --gid-owner 0 |
Descripción | En este caso se compara el grupo al que pertenece el usuario que crea el paquete (en inglés, Group ID o GID). Con esta opción podemos bloquear a todos los usuarios que no pertenezcan al grupo network, de forma que sólo éstos últimos puedan acceder a Internet; o como ya se ha dicho antes, permitir sólo a los miembros del grupo http crear paquetes que salgan por el puerto HTTP. |
Comparación | --pid-owner |
Ejemplo | iptables -A OUTPUT -m owner --pid-owner 78 |
Descripción | En este caso se comparan los paquetes en función del número de proceso que lo generó (en inglés, Process ID o PID). Esta comparación es un poco más complicada de usar, pero un ejemplo podría ser al querer limitar el envío de paquetes por el puerto HTTP: suponiendo que el proceso número 78 (PID 78) sea el único que debe tener permiso, escribiendo la regla del ejemplo lo lograríamos, eso sí, siempre y cuando este proceso no esté dividido en varios procesos paralelos (threaded). Para facilitar las cosas, podemos escribir un pequeño script que capte el PID del demonio deseado desde la salida generada por el comando ps y cree una regla para ese PID. A modo de ejemplo tienes una regla en Pid-owner.txt. |
Comparación | --sid-owner |
Ejemplo | iptables -A OUTPUT -m owner --sid-owner 100 |
Descripción | Como en el resto del grupo, esta comparación busca paquetes basándose en la identificación de sesión empleada por el programa que genera los paquetes (en inglés, Session ID o SID). El valor del SID de un proceso es el del proceso mismo y todos los subprocesos creados a partir de él. Estos subprocesos pueden ser procesos paralelos (threads) o "hijos" del proceso original. A modo de ejemplo, en un equipo con el HTTPD dividido en procesos paralelos, todos estos procesos HTTPD "hijos" deberían tener el mismo SID que su proceso "padre" (el proceso HTTPD original); la mayoría de los demonios HTTPD funcionan de esta manera, como Apache y Roxen, por citar alguno. Para mostrártelo tienes a tu disposición un pequeño script llamado Sid-owner.txt. Con unos cuantos retoques este script podría ejecutarse cada hora de forma que compruebe si el HTTPD realmente está en marcha, arrancándolo si no es así y en ese caso modificando adecuadamente la cadena OUTPUT. |
La extensión state (estado) se emplea conjuntamente con el código de seguimiento de conexiones (connection tracking) del núcleo. La comparación de estado accede a la máquina de seguimiento de conexiones y averigua en qué estado se encuentra el paquete. Éste procedimiento funciona con prácticamente todos los protocolos, incluyendo aquellos que no poseen estado, como el ICMP y el UDP. En cualquier caso por defecto habrá un intervalo de espera para la conexión, a partir del cual será eliminada de la base de datos de seguimiento de conexiones. La comparación se debe cargar explícitamente añadiendo -m state a la regla, teniendo acceso a partir de entonces a una nueva comparación llamada "estado". El concepto de comparación de estado se trata en profundidad en el capítulo La máquina de estados, ya que es un tema bastante extenso.
Table 6-13. Comparaciones de Estado
Comparación | --state |
Ejemplo | iptables -A INPUT -m state --state RELATED,ESTABLISHED |
Descripción | Esta opción le indica a la comparación state (estado) qué paquetes deben ser comparados, en función de sus estados. Por ahora hay 4 estados que puedan ser utilizados: INVALID, ESTABLISHED, NEW y RELATED (inválido, establecido, nuevo y relacionado, respectivamente). INVALID implica que el paquete no está asociado a ningún flujo o conexión conocida y que puede contener datos o cabeceras erróneas. ESTABLISHED indica que el paquete pertenece a una conexión ya establecida, totalmente válida y que "ha visto" un flujo de paquetes en ambas direcciones. NEW significa que el paquete ha creado o está creando una nueva conexión, o que está asociado a una conexión que todavía no "ha visto" paquetes en ambas direcciones. Por último, RELATED es para paquetes que empiezan una nueva conexión pero están asociados a otra conexión ya establecida (como puede ocurrir en una transferencia de datos FTP, o en un error ICMP asociado a una conexión TCP o UDP). Ten en cuenta que el estado NEW ignora los bits SYN en los paquetes TCP que están intentando empezar una nueva conexión, por lo que no debe ser usado sin modificar en los casos en que exista sólo un cortafuegos y no haya balance de carga entre diferentes cortafuegos. Sin embargo, pueden haber circunstancias donde ésto sea útil. Para mayor información sobre cómo utilizarlo, lee el capítulo La máquina de estados. |
La comparación TOS puede emplearse para comparar paquetes basándose en su campo TOS (TOS field). TOS es la abreviatura de Type Of Service (Tipo de Servicio), tiene un tamaño de 8 bits y se encuentra en las cabeceras IP. Esta comparación se carga explícitamente cuando añadimos -m tos a la regla. El Tipo de Servicio se suele usar para informar a los hosts intermedios por los que van pasando los paquetes de la llegada de un flujo y de su contenido (bueno, en realidad no hace eso, pero informa sobre cualquier requerimiento específico del flujo, como por ej. si tiene que reenviarse lo más rápidamente posible, o si necesita que se le permita contener tanta información como sea posible). De qué manera manejen los routers y administradores esa información depende exclusivamente de éllos. La mayoría la ignora, mientras que algunos intentan manejar los flujos y datos de la manera más acorde a la información del TOS.
Table 6-14. Comparaciones TOS
Comparación | --tos |
Ejemplo | iptables -A INPUT -p tcp -m tos --tos 0x16 |
Descripción | Esta comparación se usa tal como se ha descrito y puede filtrar paquetes en función de su campo TOS y la información que contiene. Ésto es de utilidad, entre otras cosas, al trabajar conjuntamente con iproute2 y con funciones avanzadas de Linux, marcando paquetes para un uso posterior. La comparación reconoce como opción un valor hexadecimal o también numérico, aunque posiblemente también acepte uno de los nombres resultantes de ejecutar "iptables -m tos -h". En el momento de escribir el tutorial, se reconocen los siguientes nombres/valores/valores hexadecimales: Minimize-Delay 16 (0x10), Maximize-Throughput 8 (0x08), Maximize-Reliability 4 (0x04), Minimize-Cost 2 (0x02) y Normal-Service 0 (0x00). Minimize-Delay se refiere a minimizar el retardo en dar curso a los paquetes (ejemplos de servicios estándar que lo requieren son telnet, SSH y FTP-control). Maximize-Throughput implica un rendimiento tan grande como sea posible (un protocolo estándar podría ser FTP-data). Maximize-Reliability pide que se maximice la fiabilidad de una conexión y que se empleen líneas tan fiables como sea posible (por ej. para BOOTP y TFTP). Minimize-Cost pide que se minimice el coste de paquetes que atraviesan cada vínculo intermedio hasta el cliente o el servidor (por ej. encontrando la ruta que cueste menos de atravesar; algunos protocolos que podrían requerir ésto son RTSP (Real Time Stream Control Protocol) y otros protocolos de transporte de flujos de video/radio). Normal-Service, por último, podría servir para cualquier protocolo que no tenga necesidades especiales. |
La comparación TTL se emplea para filtrar paquetes en función de su campo TTL (Time To Live, "tiempo de vida"), el cual se encuentra en las cabeceras IP. Este campo contiene 8 bits de datos y su valor va disminuyendo en una unidad cada vez que el paquete es procesado por un host intermedio entre el host origen y el destinatario. Si el valor TTL llega a ser 0, se transmite al remitente un mensaje informándole del problema. Este mensaje es un ICMP tipo 11 código 0 (el TTL ha tomado valor nulo durante el tránsito) o código 1 (el TTL ha tomado valor nulo durante el reensamblaje). Esta comparación únicamente efectúa un filtrado dependiendo del valor del TTL de los paquetes, pero sin cambiar nada. Para cargar esta comparación, necesitas añadir -m ttl a la regla.
Table 6-15. Comparaciones TTL
Comparación | --ttl |
Ejemplo | iptables -A OUTPUT -m ttl --ttl 60 |
Descripción | Con esta opción se especifica el valor TTL a comparar. Este valor será de tipo numérico y se comparará con el valor presente en cada uno de los paquetes. No hay inversión posible y no hay otras opciones. A modo de ejemplo, se puede emplear para efectuar chequeos en busca de fallos (debug) en tu red local, como podrían ser hosts de la red local que parecen tener problemas para conectar con otros hosts situados en Internet; o también se puede emplear para encontrar posibles troyanos que se hayan introducido en tu red. Sin embargo su uso es relativamente limitado y su utilidad depende principalmente de tu imaginación. Por ejemplo, se pueden encontrar hosts con valores anormales de TTL (debidos posiblemente a una pila TCP/IP mal implementada, o a una simple mala configuración). |
La comparación unclean no tiene opciones y sólo necesita que sea cargada explícitamente cuando quieras usarla. Sin embargo, debes tener en cuenta que se considera experimental y puede que no funcione bien en todo momento, así como tampoco se preocupará de todos los paquetes "sucios" o todos los problemas. La comparación "unclean" intenta filtrar paquetes que parecen malformados o inusuales, como aquellos paquetes con cabeceras incorrectas, checksums (sumas de verificación) incorrectos, ... Este filtro puede utilizarse, por ejemplo, para desechar (DROP) conexiones y para buscar flujos incorrectos; pero debes recordar que al no funcionar siempre correctamente, puede cortar conexiones correctas o legales.