N.dT: Utilizaremos 'chain' en este documento por cuestiones de simplicidad, aunque deberemos entender 'chain' como un conjunto, grupo o encadenamiento de reglas de filtrado.
Hay varias cosas diferentes que puede hacer con iptables. Primero las operaciones para manejar chains en general. Se empieza con tres chains predefinidas de entrada, salida y reenvio que no se pueden eliminar.
Antes de ejecutar cualquier comando iptables (ten cuidado: algunas distribuciones iniciarán iptables en sus scripts de inicialización), ten en cuenta que no habrá reglas en las chains predefinidas. t (`INPUT', `FORWARD' y `OUTPUT'), las chains INPUT y OUTPUT tendrán una política de ACCEPT, y la de FORWARD tendrá una política de DROP (puedes cambiar esto mediante la opción `forward=1' en el módulo iptables).
Cada regla especifica un conjunto de condiciones que un paquete debe cumplir, y lo que haremos si cumple dichas condiciones (efectuaremos una 'acción'). Por ejemplo, puede que quieras hacer DROP de los paquetes ICMP provinientes de la dirección 127.0.0.1. En este caso definiremos el protocolo como ICMP, la dirección de origen como 127.0.0.1 y la acción será DROP.
127.0.0.1 es el interface 'loopback' que tendrá en su máquina incluso si no dispone de una conexión real a la red. Puede hacer un 'ping' para generar paquetes dichos paquetes (un ping simplemente envia paquetes ICMP del tipo 8 (petición de eco) que todos los hosts operativos deberán responder con un paquete ICMP de tipo 0 (respuesta del eco)). Esto hace ping muy útil para el testeo.
Puedes ver aquí como funciona el ping (el parámetro '-c 1' le indica a ping que envíe un único paquete).# 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
#
Despues añadimos (-A) a la chain 'INPUT' (de entrada) una regla especificando que los paquetes que vengan de 127.0.0.1 (-s 127.0.0.1) con el protocolo ICMP (-p icmp) deberán tomar la acción DROP (-j DROP)
Una vez hecho esto, probamos la regla con un segundo ping. El programa esperará una respuesta que nunca llegará Podemos eliminar esta regla de dos formas. La primera, ya que sabemos que es la única regla en la chain de entrada (input), podemos utilizar su número para borrarla:
# iptables -D INPUT 1
La segunda forma es igual a la del comando -A, pero sustituyendo -A por -D. Esto es útil cuando tiene varias reglas complejas y no quieres tener que contarlas hasta encontrar la que buscabas. Para estos casos usaremos:
# ipchains -D INPUT -s 127.0.0.1 -p icmp -j DROP
La sintáxis de -D debe ser exáctamente igual a la de -A (o -I o -R). Si hay múltiples reglas iguales en la misma chain, sólo la primera será eliminada
La tercera y cuarta forma permite especificar un grupo de direcciones IP, como `199.95.207.0/24' o `199.95.207.0/255.255.255.0'. Ámbas indican las direcciones IP desde 199.95.207.0 a 199.95.207.255; los número después de `/' dicen las partes de la dirección IP significativas: `/32' o `/255.255.255.255' es lo normal (todas las direcciones IP de esa red). Para especificar cualquier dirección de internet podemos utilizar `/0':
Esto no se suele utilizar, ya que obtendríamos el mismo resultado sin especificar la opción de origen `-s' .# ipchains -A input -s 0/0 -j DENY
#
El protocolo puede ser precedido de un `!', para invertirlo, ej.: `-p ! TCP'.
Los paquetes que atraviesan la chain INPUT no tendrán nunca un interface de salida, así que cualquiera regla -o en esta chain no tendrá validez. Igualmente, los paquetes que atraviesan la chain OUTPUT no tendrán nunca una interfaz de entrada, así que la regla -i no funcionará.
Sólo los paquetes que atraviesen la chain de FORWARD tendrán ambos interfaces (INPUT y OUTPUT).
Es perféctamente válido especificar un interface que no existe, la regla no coincidirá con ningún paquete hasta que se active dicho interfaz. Esto es muy útil para conexiones tipo PPP y similares.
Como un caso especial, un nombre de interfaz con el sufijo '+' hará coincidir con todas los interfaces (existan o no) que empiezen por esa cadena. Por ejemplo, para indicar una regla que corresponda con todos los interfaces PPP, usaremos la opción -i ppp+.
El nombre del interface puede ser precedido por un '!' para hacer coincidir los paquetes que no correspondan con el/los interfaz(es)especificado(s).
El problema con la fragmentación es que la cabecera IP es una parte del paquete. Buscar dentro de los paquetes las cabeceras de protocolo (como lo que hacen las extensiones TCP; UDP y ICMP) no es posible, ya que estas cabeceras están contenidas en el primer fragmento.
Si estás utilizando connection tracking o NAT, los fragmentos serán juntados antes de que alcancen el código de filtrado de paquetes, de forma que no hay que preocuparse de los fragmentos. De otra forma puedes cargar el módulo 'ip_defrag.o' que realizará la misma tarea. (Nota: esto sólo es posible si eres la única conexión entre las dos redes).
De cualquier forma, es importante comprender cómo los paquetes son tratados por las reglas de filtrado. Cualquier regla que pregunta por información que no tenemos, no coincidirá. Esto significa que el primer fragmento es tratado como cualquier otro paquete. El segundo y posteriores no. La regla -p TCP --sport www nunca coincidirá con un fragmento que no sea el primero. Tampoco la regla opuesta -p TCP --sport ! www.
Puedes también especificar una regla para todos los demás
paquetes usando la opción '-f' (o '--fragment'). También es
posible indicar reglas que no correspondan con el segundo y posteriores
fragmentos precediento '-f' con '!'.
Normalmente se considera seguro dejar pasar el segundo y posteriores
paquetes ya que el filtrado afectará al primer fragmento y así
se evita la reconstrucción en el host destino. De cualquier forma
se conocen algunos bugs que permiten 'tirar' máquinas simplemente
mediante el envío de
fragmentos. Tu decides.
Nota: Los paquetes malformados (Los paquetes TCP, UDP e ICMP demasiado cortos para analizar el puerto, código ICMP y tipo) son ignorados (dropped) cuando dichos paquetes intentan llegar. Así que hay fragmentos TCP que comienzan en la posición 8.
Como ejemplo, la siguiente regla ignoraría todos los fragmentos con destino 192.168.1.1
# iptables -A OUTPUT -f -d 192.168.1.1 -j DROP
#
Para aquellos que querais especificar nuevas pruebas, en la línea de comando después de la opcion `-p' cargaremos la extensión. Para cargar nuevas pruebas explicitamente, la opción `-m' carga la extensión, después de lo cual las opciones extendidas estarán disponibles.
Para conseguir ayuda sobre extensiones, utiliza la opción
de carga (`-p' o `-m') seguida por `-h' o `--help'.
Seguidos de un opcional `!', y dos cadenas de flags, permite filtrar flags específicas de TCP. La primera cadena de flags es la máscara: la lista de flags que quieres mirar. La segunda cadena de flags determinará cual(es) serán definidas. Por ejemplo,
# iptables -A INPUT --protocol tcp --tcp-flags ALL SYN,ACK -j DENY
Opcionalmente precedida de un `!'. Es un atajo para `--tcp-flags
SYN,RST,ACK SYN'.
La solución es bloquear sólo
los paquetes de petición de conexión. Estos paquetes se llaman
SYN (si, técnicamente hay paquetes con la flag SYN
establecida y las FIN y ACK limpias, pero les llamaremos paquetes SYN para
abreviar). Para deshabilitar estos paquetes, podemos parar las peticiones
de conexión en su transcurso.
La flag `--syn' se utiliza para esto. Sólo es válido para reglas que especifiquen TCP como protocolo. Por ejemplo, para especificar intentos de conexión TCP desde 192.168.1.1:
Esta flag puede ser invertida utilizando `!', lo que significa que cada paquete que no sea un intento de inicialización de conexión.-p TCP -s 192.168.1.1 --syn
Seguida de un opcional `!' y un nombre
de tipo ICMP (como host-unreachable), un tipo numérico (ej, '3'),
o un tipo numérico y un código separado por una barra `/' (ej,
`3/3'). Una lista de los nombres de tipos ICMP puede conseguirse usando
`-p icmp --help'
Este módulo debe ser especificado explícitamente con `-m mac' o `--match mac'. Se utiliza para comparar paquetes de las direcciones de origen de Ethernet (MAC), y puede ser util para los paquetes que pasen a través de las chains INPUT y OUTPUT. Proporciona sólo una opción:
seuida de un `!' opcional, luego la dirección Ethernet en notación hexadecimal separada por dos puntos (:). Ej `--mac-source 00:60:08:91:CC:B7'.
Este módulo debe ser especificado explícitamente con `-m limit' o `--match limit'. Se usa para restringir el ratio de las coincidencias, por ejemplo para reducir mensajes de log. Sólo coincidirá un número dado de veces por segundo (por defecto 3 coincidencias por hora, con un burst de 5). Tiene dos argumentos opcionales:
seguido de un número, indica el "burst" máximo antes de que el límite anterior entre en juego.
Esta coincidencia (match)
puede ser utilizada casualmente con la acción LOG para hacer un log
limitando el ratio. Para comprender como funciona, miremos la siguiente regla,
que loggea paquetes con los parámetros por defecto del límite:
La primera vez que llega a esta regla, el paquete seráloggeado; de hecho, ya que el burst por defecto es de 5, serán los cinco primeros paquetes los loggeados. Después de esto, pasarán veinte minutos antes de que otro paquete sea loggeado por esta regla sin tener en cuenta cuantos paquetes la alcanzarán. También cada veinte minutos que sucedan sin coincidir un paquete, uno de los burst serárecuperado; si no coinciden paquetes en 100 minutos, el burst serácompletamente recuperado; vuelta al comienzo.# iptables -A FORWARD -m limit -j LOG
Este módulo debe
ser especificado explícitamente con `-m unclean o `--match unclean'.
Hace varios chequeos aleatorios de integridad en los paquetes. Este módulo
no ha sido auditado y no debería ser usado como un dispositivo de
seguridad (probablemente haga cosas mal ya que puede tener fallos en sí
mismo). No proporciona ninguna opción.
Hay dos acciones muy simples pre-compiladas: DROP y ACCEPT. Ya las conocemos. Si una regla coincide con un paquete y su acción es una de estas dos, no se consultarán más reglas: lo que pase con ese paquete ya está decidido.
Hay dos tipos de acciones
a parte de las pre-compiladas: Las extensiones y las definidas por el usuario.
Cuando un paquete coincide con una regla cuya acción es una chain definida por el usuario, los paquetes comienzan a atravesar la regla en esa chain definida por el usuario. Si esta chain no decide el futuro del paqute , entonces una vez que el paso por esa chain se ha completado, una vez atravesada la regla continua en la siguiente regla de la chain.
Es hora de arte ASCII. Considereamos dos chains: INPUT (la chain predefinida) y test (una chain definida por el usuario)
`INPUT' `test'
---------------------------- ----------------------------
| Rule1: -p ICMP -j DROP | | Rule1: -s 192.168.1.1 |
|--------------------------| |--------------------------|
| Rule2: -p TCP -j test | | Rule2: -d 192.168.1.1 |
|--------------------------| ----------------------------
| Rule3: -p UDP -j DROP |
----------------------------
Considera un paquete TCP llegando desde 192.168.1.1 hasta 1.2.3.4. Si entra por la chain INPUT y el test con la regla 1 no coincide. La regla 2 coicide y su acción es test, así que la proxima regla a examinar es el principio de test. La regla 1 en test coincide pero no especifica una acción, así que la siguiente regla que se examina es la 2. Estas no coinciden, así que rechazamos la chain. Volvemos a la chain INPUT, donde habiamos examinado la regla 2, así que examinamos la regla 3, que tampoco coincide.
Así que el paquete
es:
v __________________________
`INPUT' | / `test' v
------------------------|--/ -----------------------|----
| Rule1 | /| | Rule1 | |
|-----------------------|/-| |----------------------|---|
| Rule2 / | | Rule2 | |
|--------------------------| -----------------------v----
| Rule3 /--+___________________________/
------------------------|---
v
Las chains definidas por el usuario pueden saltar a otras chains definidas por el usuario (pero no se pueden hacer bucles: Los paquetes serán ignorados si se encuentran en un bucle)
El otro tipo de acciones son una extensión. Una extensión de una acción es un módulo del kernel, y una extensión opcional de iptables permite una nueva opcion de linea de comandos. Hay varios tipos de extensiones por defecto en la distribucción de netfilter.
Este modulo ofrece al kernel poder logar los paquetes coincidentes. Esto ofrece opciones adicionales:
seguido por el nombre o nímero de un nivel. Los nombres validos son 'debug', 'info', 'notice', 'warning', 'err', 'crtl', 'alert' y 'emerg', que corresponden a los números de 0 a 7. Mira la página man de syslog.conf para ver la explicación de estos niveles.
Seguido de una cadena de caracteres de mas de 14 caracteres, El mensaje se manda al principio del log de mensajes, para permitir su identificación unica.
Este módulo es el más utilizado despues de un limite de acciones, así no tienes que inundar tus logs
Este módulo tiene el mismo efecto que 'DROP', a no ser que se envie un mensaje de error de ICMP 'port unreachable'. Date cuenta que el mensaje de error de ICMP no se manda si (ver la RFC 1122)
· El paquete filtrado era un mensaje de error ICMP en primer lugar o un tipo de ICMP desconocido
· El paquete filtrado era un fragmento sin cabecera
· Se han mandado demasiados mensajes de error ICMP al destinatario recientemente.
Hay dos acciones especiales predefinidas: RETURN y QUEUE
RETURN tiene el mismo efecto que desprenderse del final de la chain: para una chain predefinida, la politica de la chain es ejecutarse. Para una regla definida por un usuario, se continuará con la anterior chain, justo antes de la regla que salto a esta chain.
QUEUE es una acción especial, la cual encola los paquetes para procesarla en el espacio del usuario. A no ser que haya algo esperando por el paquete ( por ejemplo que no haya sido escrito todavia), el paquete sera dropado.
Una característica muy util de iptables es su capacidad de agrupar reglas dentro de una chain. Se puede llamar a estas chain como se quiera, pero es recomendable utilizar las letras minusculas para evitar confusiones con las chain predefinidas y las acciones. Una chain puede tener una máximo de 16 caracteres.
Vamos a crear una nueva chain. Como soy una persona con mucha imaginación, la vamos a llamar test. Usaremos la opción '-N' o '--new-chain':
# iptables -N test
#
Es asi de simple. Ahora puedes poner todas las reglas que quieras como hemos definido antes.
Borrar una chain es muy simple, usando la opción '-X' o '--delete-chain'. ¿Por que '-X'? Bueno, todas las adecuadas ya estaban usadas.
# iptables -X test
#
Hay unas cuantas restrinciones para borrar chains: Esta debe estar vacia (mira vaciar una Chain a continuación) y no puede ser una acción de una regla. No puedes borrar ninguna de la tres reglas predefinidas.
Si no especificas una chain, todas las chain definidas por el usuario se borraran, si es posible.
Hay una forma simple de vaciar todas las reglas de una chain, usando '-F' (o '--flush')
# ipchains -F forward
#
Si no especificas una chain, entonces todas las chain serán vaciadas
Se puede listar todas las reglas en una chain usando el comando '-L'
El 'refcnt' lista para cada chain definida por el usuario, el número de reglas que tiene cada chain y las acciones de esta. Esto debe ser cero ( y la chain estara vacia) antes de que la chain se pueda borrar.
Si se omite el nombre de la chain, se listarán todas las chain, menos las vacias.
Hay tres opcioines que pueden acompañar a '-L'. La opción '-n' (numerico) es muy usada para prevenir que iptables busque la la dirección IP, lo cual (en el caso de usar DNS como casi todo el mundo) causará largas esperas si tu DNS no esta configurado adecuadamente, o si se tiene definido un filtro la salida de peticiones del DNS. Esto causa que los puertos TCP y UDP imprimidos sean bastantes mas que los nombres.
La opción '-v' muestra todos los detalles de las reglas , asi como la cuenta de paquetes y bytes, la comparación TOS, y los interfaces. De otra forma estos valores serán omitidos.
Nota que los contadores de paquetes y bytes se imprimen usando los sufijos 'K','M' o 'G' para 1000, 1000000 y 100000000 respectivamente. Usando la flag '-x' (expande números) imprime los números completos, no como son de grandes.
Suele ser util resetear los contadores. Esto se puede realizar la opción '-Z' (o '--zero').
El problema de realizar esta acción es que a veces necesitas saber el valor del contador inmediatamente despues de resetearlo. En el anterior ejemplo, algunos paquetes pueden pasar entre los comandos '-L' y '-Z' . Por esta razón se puede usar '-L' y '-Z' a la vez , pasar resetear los contadores a la vez que los lees.
Estamos tocando muy por encima lo que ocurre cuando un paquete llega al final de una chain predefinida, cuando discutimos como un paquete atraviesa una regla rápidamente, la politica de la chain determina el destino del paquete. Solo las chain predefinidas (INPUT, OUTPUT y FORDWARD) tienen politicas, por que si un paquete llega al final de una chain definida por el usuario, regresa a la chain anterior.
La politica puede ser ACCEPT o DROP.
Hay módulos en la distribución de netfilter llamados ichains.o y ipfwadm.o. Inserta uno de estos en tu kernel (NOTA: Hay incopatibilidades con iptables.o, ip_conntrack.o y ip_nat.o!). Entonces podras usar ipchains o ipfwadm como en los buenos viejos tiempos.
Esto será soportado todavia por un tiempo. He pensado en una formula razonable que es 2* [noticia de cambio - primera versión estable],mas alla de la fecha en que una versión estable este lista.
El significado para ipfwadm, el final del soporte (Toma fecha reales):
2 * [Octubre 1997 (2.1.102 release) - Marzo 1995 (ipfwadm 1.0)]
+ Enero 1999 (2.2.0 release)
= Noviembre 2003.
El significado para ipchains, el final del soporte (Toma datos reales):
2 * [Agosto 1999 (2.3.15 release) - Octubre 1997 (2.2.0 release)]
+ Enero 2000 (2.3.0 release?)
= Septiembre 2003.
Asi que no te debes preocupar hasta el 2004