Iptables, introducción
Introducción a IPTABLES
El objetivo es, mediante iptables, lograr cierta protección y seguridad. Iptables es una utilidad de linux que se encarga de darle directivas al kernel, acerca del filtrado de paquetes TCP/IP.
El kernel de linux posee, predefinidas, 3 cadenas (chains) de reglas: INPUT (lo que entra), FORWARD (lo que se redirige) y OUTPUT (lo que sale). Cada paquete TCP/IP que ingresa/atraviesa/sale desde/hacia una maquina con iptables funcionando, pasará por la cadena INPUT, FORWARD o OUTPUT respectivamente. Las cadenas,no son mas que un listado de reglas, con las cuales controlamos cada uno de los paquetes que pasan. Una regla consta de 2 partes, y no es mas que una condición y una acción. Si se cumple la condición se ejecuta la acción. Si un paquete atravesó todas las reglas de una cadena, sin hallar coincidencia, iptables se fijará en la politica por defecto de esa cadena(default policy).
Primero, tener en cuenta que el forwarding debe estar habilitado:
#echo 1 > /proc/sys/net/ipv4/ip_forward
Y también que para cambiar las reglas, primero hay que “borrar” las anteriores:
# iptables -F
# iptables -t nat -F
Supongamos la siguiente situación: una red local 192.168.1.0 con 50 PC’s, de las cuales destacaremos:
1) aquihacker.mired.lan (192.168.1.15)
2) neutral.mired.lan (192.168.1.1 ![]()
3) jose.mired.lan (192.168.1.20)
Nosotros somos los operadores de “jose.mired.lan”, estamos corriendo un servicio ftp, y estamos enterados de que el muchacho que usa “aquihacker”, es alguien muy curioso, que le gusta investigar en máquinas ajenas, utilizando su interfaz de red.
Vamos a ver cual es el estado de nuestras 3 cadenas, listando lo que hay en ellas. Para eso ejecutamos el siguiente comando:
# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Si la salida obtenida no se parece a la precedente, significa que no estan instalados los módulos correspondientes en el kernel, o que ya hay un firewall funcionando, o que ya se ejecutó un script probablemente en el inicio del sistema donde se cargan las reglas del firewall.
Si la salida obtenida es igual a la escrita arriba quiere decir que el firewall esta aceptando todos los paquetes, o lo que es lo mismo, no filtra absolutamente nada. Esto nos indica 2 cosas:
- Las 3 cadenas (INPUT/FORWARD/OUTPUT) estan vacías
- Las 3 cadenas tienen como politica default “ACCEPT” (aceptar).
Si hacemos ping a localhost (nosotros mismos) recibimos como respuesta:
# ping localhost
PING localhost.localdomain (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
64 bytes from localhost.localdomain (127.0.0.1): icmp_seq=0 ttl=255 time=0.3ms
Vamos a agregar una regla, para entender el funcionamiento:
# iptables –append INPUT –protocol icmp –source 127.0.0.1 –jump DROP
Que significa: Agregar (append) la siguiente regla a la cadena INPUT: al recibir un paquete del tipo icmp (–protocol) con origen (–source) “127.0.0.1″ y con cualquier destino (ya que no lo especificamos), enviamos ese paquete (–jump) a DROP, que es lo mismo que “rechazar”. Entonces listemos otra vez las reglas que tenemos cargadas:
# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP icmp — 127.0.0.1 0.0.0.0/0
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
En la cadena INPUT, se nos agregó una regla, cuya función (a modo de ejemplo) es impedir que se haga ping desde nuestra propia máquina:
# ping localhost
PING localhost.localdomain (127.0.0.1) from 127.0.0.1 : 56(84) bytes of data.
(y se quedará esperando una respuesta que nunca llegará…)
Veremos que desde la pc “aquihacker”, hacemos ping sin problemas, y nuestra maquina le responde.
# ping malevolo.mired.lan
PING jose.mired.lan (192.168.1.20) from 192.168.1.15 : 56(84) bytes of data.
64 bytes from 192.168.1.20: icmp_seq=0 ttl=255 time=2.524 msec
64 bytes from 192.168.1.20: icmp_seq=1 ttl=255 time=1.319 msec
Con lo cual, con un simple ping, nuestro amigo operador de “aquihacker” puede notar la presencia de nuestro PC.
Restringiendo paquetes provenientes del exterior
Puesto que nuestro firewall está filtrando los paquetes ICMP locales, y deja pasar los remotos. Vamos a cambiar un poco las reglas “del juego”. Borramos la regla que anteriormente agregamos:
# iptables –delete INPUT –protocol icmp –source 127.0.0.1 –jump DROP
Esto se logra con la opción “-D”, y el resto, es la transcripción EXACTA de la regla que queremos borrar.
NOTA: conociendo que era la única regla, hubieramos logrado el mismo resultado escribiendo:
# iptables –delete INPUT 1
Ahora vamos a restringir el acceso a paquetes icmp desde la red:
# iptables -A INPUT -p icmp -s 192.168.1.15 -j DROP
Nota.- Es indistinto escribir -A o –append, -p o –protocol, etc.
Ahora, listamos nuestra cadena INPUT:
# iptables -nL INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP icmp — 192.168.1.15 0.0.0.0/0
Ahora cualquier paquete icmp con origen en 192.168.1.15 será “DROPeado”. Por ello, cuando nuestro amigo curioso hace ping desde su máquina a la nuestra, jamás tendrá respuesta..
# ping jose.mired.lan
PING malevolo.mired.lan (192.168.1.20) from 192.168.1.15 : 56(84) bytes of data.
Nuestro amigo, extrañado por que el comando ping no respondió, en un principio pensó que tendríamos la PC apagada, pero luego ejecutó…
# ftp malevolo.mired.lan
Connected to malevolo.mired.lan.
220 malevolo FTP server (Version wu-2.6.1-16) ready.
Name (malevolo:root):
Nos olvidamos que teníamos un FTP server corriendo por lo que debemos agregar la siguiente regla:
# iptables -A INPUT -p tcp -s 192.168.1.15 –dport 21 -j DROP
Listamos la cadena INPUT y obtenemos:
# /sbin/iptables -nL INPUT
Chain INPUT (policy ACCEPT)
target prot opt source destination
DROP icmp — 192.168.1.15 0.0.0.0/0
DROP tcp — 192.168.1.15 0.0.0.0/0 tcp dpt:21
Ahora pensemos lo siguiente: ¿que pasa si en nuestra red, de las 50 PC’s que la conforman, la mayoría son “amigos curiosos” ?. Agregar una regla para cada uno de ellos sería un trabajo tedioso, y poco eficiente. Si bien todas estas reglas se aplicarían sin problemas y son correctas sintácticamente, es mas aconsejable seguir la filosofía de “Todo lo que no está explicitamente permitido, entonces está prohibido”.
Para lograr esto setearemos la politica por defecto en DROP (descartar). Cualquier paquete que circula por la cadena INPUT es DROPeado si no coincide con ninguna regla. En caso de que estén editando el iptables desde una consola local, pueden ignorar el parrafo siguiente, pero para aquellos que estan toqueteando iptables remotamente (telnet, ssh …) si setean como politica DROP para la cadena INPUT se les caera la conexión, para evitarlo previamente deberan agregar la siguiente regla:
# iptables -A INPUT -p tcp -s #ORIGEN# –dport #PUERTO# -j DROP
#ORIGEN# es la IP desde donde se están conectando al linux con iptables y #PUERTO# debe ser el 22 (si es conexion ssh) o 23 (si usan telnet).
Ahora continuaremos seteando la política de INPUT en DROP (con la opción -P)
# iptables -P INPUT -j DROP
Vaciamos todas las cadenas con la opción -F (flush)
# iptables -F
Listamos lo que tenemos:
# iptables -nL INPUT
Chain INPUT (policy DROP)
target prot opt source destination
Aunque no tengamos ninguna regla, nadie va a poder acceder a nuestra PC por ningun motivo. Justamente, cualquier paquete que entra, es expuesto a cada regla de la cadena (en nuestro caso nuestra cadena esta vacía), al no encontrar coincidencias, el destino del paquete, lo decide la política de la cadena, osea DROP. El problema aquí es que aunque nosotros podamos realizar
conexiones salientes, las respuestas de los servidores serán descartadas. Para solucionar esto, agregamos la siguiente regla:
# iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
Por la cual dejamos pasar cualquier paquete cuya conexión ya se ha establecido (ESTABLISHED), o cuya conexión es nueva, pero está relacionada a una conexión ya establecida (RELATED). Listamos nuevamente:
# iptables -nL INPUT
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all — 0.0.0.0/0 0.0.0.0/0 state
RELATED,ESTABLISHED
Con lo cual, nadie podrá iniciar una conexion a nuestra maquina. Ahora podemos empezar a permitir conexiones. Acceso local:
# iptables -A INPUT -i lo -s 127.0.0.1 -j ACCEPT
-i lo : Se especifica como interfaz de red a localhost (lo).
# iptables -nL INPUT
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all — 0.0.0.0/0 0.0.0.0/0 state
RELATED,ESTABLISHED
ACCEPT all — 127.0.0.1 0.0.0.0/0
Le permito a “neutral”, el acceso ftp (puerto 21)
# iptables -A INPUT -p tcp -s 192.168.1.18 –dport 21 -j ACCEPT
# iptables -nL INPUT
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT all — 0.0.0.0/0 0.0.0.0/0 state
RELATED,ESTABLISHED
ACCEPT all — 127.0.0.1 0.0.0.0/0
ACCEPT tcp — 192.168.1.18 0.0.0.0/0 tcp dpt:21
Los cambios realizados en iptables no quedan guardados sino que se almacenan en memoria, y, al reiniciar, los cambios se borrarán. Por lo que es preferible guardarlos en un script que se ejecute automaticamente al inicio y preferiblemente antes de levantar cualquier servicio inclusive la interfaz de red.
EJEMPLO COMPLETO DE SCRIPT DE CONFIGURACION DE IPTABLES (editar, nombrar y copiar en /etc/init.d/iptables y crear un enlace hacia el script en /etc/network/if-up.d)
Nota.- Naturalmente adaptar a las necesidades de cada cual.
#!/usr/bash
# habilitar el forward
echo 1 > /proc/sys/net/ipv4/ip_forward
#Borrar anteriores reglas
iptables -F
iptables -X
iptables -Z
# Vaciar la tabla NAT
iptables -t nat -F
# Si se quiere establecer la politica por defecto
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT
# Habilito el SNAT si la IP es fija
iptables -t nat -A POSTROUTING -o eth0 -j SNAT –to 111.111.111.111
# Habilito el NAT si la IP no es fija (o la anterior o esta)
iptables -t nat -A POSTROUTING -p tcp -s 192.168.0.0/24 -d 0.0.0.0/0 -j MASQUERADE
# Crear una regla que permita el paso entre dos redes en la tabla del firewall
# para dos tarjetas de red
iptables -A FORWARD –in-interface eth0 –out-interface eth1 -j ACCEPT
# Tener acceso al firewall desde la red local
iptables -A INPUT -s 192.168.10.0/24 -i eth1 -j ACCEPT
# Dejar pasar los paquetes ICMP (los pings)
iptables -A INPUT -i eth0 -p ICMP -j ACCEPT
#Dejar todo lo que entre y salga de localhost (lo)
iptables -A INPUT -i lo -j ACCEPT
# Permito conexiones al puerto 80 (HTTP) tambe es pot posar un rang de ports 20:80
iptables -A INPUT -i eth0 -p TCP –dport 80 -m state –state NEW -j ACCEPT
# Permito conexiones al puerto 22 (SSH)
iptables -A INPUT -i eth0 -p TCP –dport 22 -m state –state NEW -j ACCEPT
# Cerrar el puerto 111 TCP
iptables -A INPUT -p tcp –dport 111 -j DROP
# bloquear totalmente una ip de una red
iptables -A INPUT -s 192.168.0.3/32 -j DROP
# Permitir conesiones al puerto 4662 de amule
iptables -A INPUT -i eth0 -p TCP –dport 4662 -m state –state NEW -j ACCEPT
iptables -A INPUT -i eth0 -p UDP –dport 4662 -m state –state NEW -j ACCEPT
# Acepto paquetes de conexiones ya establecidas
iptables -A INPUT -p TCP -m state –state RELATED -j ACCEPT
# Rechazamos paquetes de conexiones nuevas
iptables -A INPUT -i eth0 -m state –state NEW,INVALID -j DROP
# Rechazamos paquetes de forwarding de conexiones no establecidas
iptables -A FORWARD -i eth0 -m state –state NEW,INVALID -j DROP
# Redireccionar las conexiones a un puerto de un ordenador de la LAN
# Por ejemplo, al puerto 80 de un ordenador en la red interna (192.168.0.111).
iptables -t nat -A PREROUTING -i eth0 -p tcp –dport 80 -j DNAT –to 192.168.0.111:80
# Redireccionar el puerto 2022 haciendo de NAT o firewall hacia el puerto 22 (ssh) de # un ordenador de la red interna.
iptables -t nat -A PREROUTING -i eth0 -p tcp –dport 2022 -j DNAT –to 192.168.0.111:22
# Cerrar el resto de paquetes
iptables -A INPUT -i eth0 -m state –state NEW,INVALID -j DROP
iptables -A FORWARD -i eth0 -m state –state NEW,INVALID -j DROP
#nat para mlnet, http, ssh, ftp. (VERIFICAR)
iptables -t nat -A PREROUTING -i eth0 -p TCP –dport 4662 -j DNAT –to 192.168.0.2:4662
iptables -t nat -A PREROUTING -i eth0 -p UDP –dport 4662 -j DNAT –to 192.168.0.2:4662
iptables -t nat -A PREROUTING -i eth0 -p TCP –dport 22 -j DNAT –to 192.168.0.2:22
iptables -t nat -A PREROUTING -i eth0 -p TCP –dport 21 -j DNAT –to 192.168.0.2:21
iptables -t nat -A PREROUTING -i eth0 -p TCP –dport 20 -j DNAT –to 192.168.0.2:20
iptables -t nat -A PREROUTING -i eth0 -p TCP –dport 80 -j DNAT –to 192.168.0.2:80
# puertos samba
iptables -A INPUT -i eth0 -s 192.168.2.0/24 -p tcp –dport 137 -j ACCEPT
iptables -A INPUT -i eth0 -s 192.168.2.0/24 -p udp –dport 137 -j ACCEPT
iptables -A INPUT -i eth0 -s 192.168.2.0/24 -p tcp –dport 138 -j ACCEPT
iptables -A INPUT -i eth0 -s 192.168.2.0/24 -p udp –dport 138 -j ACCEPT
iptables -A INPUT -i eth0 -s 192.168.2.0/24 -p tcp –dport 139 -j ACCEPT
iptables -A INPUT -i eth0 -s 192.168.2.0/24 -p udp –dport 139 -j ACCEPT
iptables -A INPUT -i eth0 -s 192.168.2.0/24 -p tcp –dport 445 -j ACCEPT
iptables -A INPUT -i eth0 -s 192.168.2.0/24 -p udp –dport 445 -j ACCEPT