|
|
Este documento está disponible en los siguientes idiomas: English Castellano ChineseGB Deutsch Francais Nederlands Russian Turkce |
por Vincent Renardias <vincent(at)renardias.com> Sobre el autor: Usuario de GNU/Linux desde 1993, Vincenct Renardias comenzó a involucrarse en su desarrollo en 1996: desarrollador de Debian, autor de la traducción francesa de The Gimp y el entorno GNOME, creador del grupo de usuarios de Linux en Marsella (PLUG), ... Actualmente director de I+D de la compañia EFB2, sigue contribuyendo al sistema GNU/Linux. Taducido al español por: Roberto Hernando (homepage) Contenidos: |
El filtrado de paquetes con LinuxResumen:
Este artículo ha sido publicado en un número especial sobre la seguridad de Linux Magazine France. El editor, los autores y los traductores han aceptado amablemente que todos los artículos de ese número especial sean publicados en LinuxFocus. En consecuencia, LinuxFocus os "ofrecerá" esos artículos a medida que se vayan traduciendo al inglés. Este resumen se reproducirá en todos los artículos que tengan el mismo origen.
|
El mecanismo de filtrado puede considerarse como una malla que retiene
ciertos paquetes no deseados. Lo más importante es
encontrar el tamaño adecuado del mallado, así como el lugar donde ponerla.
Para poder filtrar apropiadamente los paquetes, el mecanismo
de filtrado debe intercalarse físicamente entre la red a proteger
y el "resto del mundo". En la práctica, esto se hace con
una máquina que tenga dos interfaces de red (normalmente Ethernet),
una conectada a la red interna y la otra al router (encaminador) que
permite el acceso al exterior. De esta forma, las comunicaciones
pasarán obligatoriamente por el cortafuegos que las bloqueará o no
según su contenido.
La máquina con el mecanismo de filtrado se puede configurar de 3
formas diferentes:
- gateway (pasarela) "simple": es la configuración más habitual. La
máquina se utiliza como una pasarela entre dos redes o subredes.
Las computadoras en la red local se deben configuradar para usar
el cortafuegos, en vez del router, como su ruta por defecto.
- pasarela "Proxy-ARP": la configuración anterior implica la división de la
red en dos subredes, con lo que se pierde la mitad de las direcciones IP
disponibles, desperdiciándose un bit. Como ejemplo, en una subred con 16
direcciones (con una submáscara de 28 bits), sólo 14 estarán disponibles, ya
que dos direcciones son para la red y el broadcast. Añadiendo 1 bit
a la máscara de subred, bajamos de 14 a 6 direcciones disponibles (8 IPs menos
las direcciones de red y broadcast). Cuando no se puede perder
la mitad de las IPs disponibles se utiliza esta técnica, que está
explicada un poco después en este artículo. Además, esta técnica no
requiere ningún cambio en la configuración de red de las máquinas
existentes, ni del router, ni de las computadoras protegidas.
- puente Ethernet (Ethernet bridge): instalando una pasarela
Ethernet (no una pasarela IP) se consigue un mecanismo de filtrado
invisible desde otras máquinas. Esta configuración se puede llevar a cabo
sin asignar direcciones IP a las interfaces Ethernet. La máquina se convierte
en indetectable mediante ping, traceroute, etc. Tengamos en cuenta
que una implementación de filtrado por paquetes
requiere un núcleo 2.2.x, ya que esta característica todavía no está
implementada en los núcleos 2.4.x
Ahora que sabemos dónde instalar nuestro filtro, debemos definir
que tendrá que bloquear o qué aceptar.
Existen dos formas de configurar el filtro:
- La buena: no se permite pasar a ningún paquete, a no ser que lo autorice
explícitamente alguna regla.
- La mala: (desgraciadamente, usada a menudo) los paquetes explícitamente
prohibidos se paran, todos los demás se aceptan.
Es sencillo explicarlo: en el primer caso, olvidar una regla lleva a que
un servicio no funcione apropiadamente o no funcione en absoluto.
En el segundo caso, olvidar una regla crea una vulnerabilidad
potencial que puede ser difícil de encontrar... si la encontramos.
La aplicación de filtrado más utilizada con Linux 2.4 es Netfilter; reemplaza con creces a ípchains', utilizada con los núcleos Linux 2.2. Netfilter tiene dos partes: un componente del núcleo que debe compilarse en el núcleo y el comando íptables' que ya debería estar disponible en su sistema.
Un ejemplo comentado es mejor que un gran discurso, describiremos cómo instalar y configurar un mecanismo de filtrado. Primero, la máquina se configurará como una pasarela mediante Proxy-ARP para limitar el número de direcciones IP y seguidamente configuraremos el sistema de filtrado.
El autor prefiere la distribución Debian para este tipo de instalación, pero cualquier otra distribución servirá.
Primero, compruebe que su núcleo soporta Netfilter. Si esto es así, deberá aparecer lo siguiente en los mensajes de arranque:
ip_conntrack (4095 buckets, 32760 max)
ip_tables: (c)2000 Netfilter core team
En otro caso, tendrá que recompilar el núcleo después de haber activado el componente Netfilter. Las correspondientes opciones se encuentran en el submenú "Network Packet Filtering (Filtrado de Paquetes de Red)" del menú "Networking Options (Opciones de Red)". Elija las opciones que necesite de la sección "Netfilter Configuration (Configuración de Netfilter)". Si duda, puede elegir todas. Además es mejor incluir Netfilter en el núcleo y no usar módulos. Si por una razón u otra los módulos de Netfilter desaparecen o no se cargan el filtrado podría no funcionar y mejor no hablamos de los peligros que esto conllevaría.
También debería instalar el paquete íproute2' (esto último no es
obligatorio pero nuestro ejemplo lo utilizará, ya que nos permite
simplificar el script de configuración). Con Debian, es suficiente con
escribir el comando ápt-get install iproute'.
Con otras distribuciones, obtenga el paquete correspondiente de la
forma habitual o bien puede instalarlo a partir del código fuente que
puede obtener en la siguiente dirección:
ftp://ftp.inr.ac.ru/ip-routing/
Ahora hay que configurar las dos tarjetas Ethernet. Tengamos
en cuenta que el núcleo de Linux cuando autodetecta el hardware detiene
la búsqueda de tarjetas de red tan pronto como encuentra una. Por
tanto, sólo se detectará la primera.
Una sencilla solución a este problema es añadir la siguiente línea
al fichero lilo.conf:
append="ether=0,0,eth1"
Después tendremos que configurar las interfaces Ethernet. El método
que elegiremos nos permitirá utilizar la misma dirección IP para ambas
tarjetas, con lo que ahorraremos una dirección.
Asumamos que tenemos la subred 10.1.2.96/28, que incluye
las direcciones de la 10.1.2.96 a la 10.1.2.111. El router tendrá la
dirección 10.1.2.97 y nuestra máquina de filtrado la 10.1.2.98. La
interfaz eth0 se conectará al router a través de un
cable cruzado RJ45 si ambas tarjetas se conectan directamente
sin utilizar un hub o un switch; la interfaz eth1 se conectará
al hub/switch y desde aquí a las máquinas de la red local.
Así pues, ambas interfaces se configurarán con los siguientes parámetros:
address : 10.1.2.98 netmask : 255.255.255.240 network : 10.1.2.96 broadcast: 10.1.2.111 gateway : 10.1.2.97
A continuación utilizaremos el siguiente script que deberemos ejecutar
tras la configuración inicial de las tarjetas de red.
net.vars: Variables de configuración PREFIX=10.1.2 DMZ_ADDR=$PREFIX.96/28 # Definiciones de la Interfaz BAD_IFACE=eth0 DMZ_IFACE=eth1 ROUTER=$PREFIX.97 net-config.sh: script de configuración de red #!/bin/sh # Descomentar la siguiente línea para visualizar los comandos tras su ejecución # set -x # Se leen las variables definidas en el fichero anterior source /etc/init.d/net.vars # Se borran las rutas actuales de la red local ip route del $PREFIX.96/28 dev $BAD_IFACE ip route del $PREFIX.96/28 dev $DMZ_IFACE # Se define que la red local es accesible a través de eth1 # y el router a través de eth0. ip route add $ROUTER dev $BAD_IFACE ip route add $PREFIX.96/28 dev $DMZ_IFACE # Se activa Proxy-ARP para las dos interfaces echo 1 > /proc/sys/net/ipv4/conf/eth0/proxy_arp echo 1 > /proc/sys/net/ipv4/conf/eth1/proxy_arp # Activamos "IP forwarding" para permitir a los paquetes que llegan a una tarjeta # enrutarse hacia la otra echo 1 > /proc/sys/net/ipv4/ip_forward
Volvamos al mecanismo Proxy-ARP requerido para nuestra
configuración.
Cuando un máquina habla con otra en la misma red, necesita conocer
la dirección Ethernet (o dirección MAC o dirección hardware) correspondiente
a su dirección IP. Entonces la máquina origen difunde ("hace un broadcast")
la pregunta "¿cuál es la dirección MAC de la interfaz cuya dirección IP es
1.2.3.4?", y la máquina destino debe responder.
Aquí tenemos un ejemplo de dicha "charla" vista usando tcpdump:
- la petición: la máquina 172.16.6.72 pregunta la dirección MAC
correspondiente a la dirección IP 172.16.6.10.
19:46:15.702516 arp who-has 172.16.6.10 tell
172.16.6.72
- la respuesta: la máquina 172.16.6.10 da su número de tarjeta.
19:46:15.702747 arp reply 172.16.6.10 is-at
0:a0:4b:7:43:71
Esto nos conduce al final de esta pequeña explicación: las peticiones ARP se hacen mediante difusión, por lo que están limitadas a una única red física. Así pues la petición de una máquina protegida para encontrar la dirección MAC del router debería ser bloqueada por la máquina de filtrado. Activando la característica Proxy-ARP solventaremos este problema pidiendo explícitamente que las peticiones y respuestas ARP que lleguen por una tarjeta se propaguen hacia la otra, y viceversa.
En este punto, debería tener una red trabajando con una máquina controlando todo el tráfico entre la red local y el exterior.
Ahora, debemos configurar el filtrado mediante Netfilter.
Netfilter permite actuar directamente en el flujo de paquetes.
En la configuración básica los paquetes son controlados por
tres cadenas de reglas:
- INPUT: para los paquetes que llegan a través de una interfaz,
- FORWARD: para todos los paquetes transmitidos desde una interfaz
hacia la otra,
- OUTPUT: para los paquetes que salen de una interfaz.
El comando íptables' permite añadir, cambiar o borrar reglas
en cada una de estas cadenas para modificar el entorno de filtrado.
Más aún, cada cadena tiene una política por defecto, esto es, sabe
qué hacer cuando ninguna regla en la cadena afecta a un paquete.
Las cuatro opciones más comunes son:
- ACCEPT: el paquete puede pasar,
- REJECT: el paquete es rechazado y se envía el paquete de
error asociado (ICMP Port Unreachable, TCP RESET, según el caso),
- LOG: escribe una notificación de paquete en syslog,
- DROP: el paquete es ignorado y no se envía ninguna respuesta.
Aquí están las principales opciones de iptables que nos permiten manipular cadenas enteras. Las explicaremos con detalle más tarde:
-N: crea una nueva cadena.
-X: borra una cadena vacía.
-P: cambia la política por defecto de una cadena.
-L: lista las reglas en una cadena.
-F: elimina todas las reglas en una cadena.
-Z: pone a cero los contadores de bytes y paquetes
que han pasado por la cadena.
Para modificar una cadena se dispone de los siguientes comandos:
-A: añade una regla al final de una cadena.
-I: inserta una nueva regla en una posición dada en una cadena.
-R: reemplaza una cadena dada en una cadena
-D: borra una regla en una cadena, bien usando su número
o bien describiendo la regla.
Veamos un pequeño ejemplo práctico: bloquearemos las respuestas
PING (es decir el tipo écho-reply' de los paquetes ICMP) que lleguen
desde una máquina dada.
Primero, veamos que podemos hacer PING a la máquina dada:
# ping -c 1 172.16.6.74 PING 172.16.6.74 (172.16.6.74): 56 data bytes 64 bytes from 172.16.6.74: icmp_seq=0 ttl=255 time=0.6 ms --- 172.16.6.74 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.6/0.6/0.6 msAhora, añadimos una regla en la cadena INPUT que interceptará los paquetes que vengan de la máquina 172.16.6.74 ('-s 172.16.6.74') del tipo ICMP-Reply ('-p icmp --icmp-type echo-reply'). Estos paquetes se ignorarán ('-j DROP').
# iptables -A INPUT -s 172.16.6.74 -p icmp --icmp-type echo-reply -j DROP
Hagamos de nuevo ping a la máquina:
# ping -c 3 172.16.6.74 PING 172.16.6.74 (172.16.6.74): 56 data bytes --- 172.16.6.74 ping statistics --- 3 packets transmitted, 0 packets received, 100% packet loss
Como se esperaba, la respuesta no pasa. Podemos comprobar que se han bloqueado las tres respuestas (3 paquetes, para un total de 252 bytes):
# iptables -L INPUT -v Chain INPUT (policy ACCEPT 604K packets, 482M bytes) pkts bytes target prot opt in out source destination 3 252 DROP icmp -- any any 172.16.6.74 anywhere
Para volver a la situación inicial, sólo tenemos que borrar la primerar regla de la cadena INPUT:
# iptables -D INPUT 1
Y el PING debería funcionar de nuevo:
# ping -c 1 172.16.6.74 PING 172.16.6.74 (172.16.6.74): 56 data bytes 64 bytes from 172.16.6.74: icmp_seq=0 ttl=255 time=0.6 ms --- 172.16.6.74 ping statistics --- 1 packets transmitted, 1 packets received, 0% packet loss round-trip min/avg/max = 0.6/0.6/0.6 ms #
¡Funciona!
Puede añadir otras cadenas a las 3 predefinidas (que nunca podrá eliminar) y hacer que cierto tráfico vaya por ellas. Esto puede ser útil, por ejemplo, para impedir reglas duplicadas en varias cadenas.
Pasemos a configurar las reglas necesarias para un cortafuegos
mínimo. Permitirá ssh, DNS, http y smtp y nada más.
Para simplificar, los comandos de configuración se han escrito
en un script. El script comienza borrando la configuración actual
antes de establecer una nueva. Este pequeño truco permite ejecutar
el script cuando la configuración está activa sin el riesgo de
duplicar reglas.
rc.firewall #!/bin/sh # Borrando las reglas iptables -F iptables -F INPUT iptables -F OUTPUT iptables -F FORWARD # La cadena se construye según la dirección. # bad = eth0 (exterior) # dmz = eth1 (interior) iptables -X bad-dmz iptables -N bad-dmz iptables -X dmz-bad iptables -N dmz-bad iptables -X icmp-acc iptables -N icmp-acc iptables -X log-and-drop iptables -N log-and-drop # Cadena específica utilizada para registrar los paquetes antes de bloquearlos iptables -A log-and-drop -j LOG --log-prefix "drop " iptables -A log-and-drop -j DROP # Los paquetes con el indicador TCP activados se eliminan # y lo mismo para los que no tienen ningún indicador (a menudo usado por Nmap) iptables -A FORWARD -p tcp --tcp-flags ALL ALL -j log-and-drop iptables -A FORWARD -p tcp --tcp-flags ALL NONE -j log-and-drop # Los paquetes de clases de direcciones reservadas se eliminan # y lo mismo para multicast iptables -A FORWARD -i eth+ -s 224.0.0.0/4 -j log-and-drop iptables -A FORWARD -i eth+ -s 192.168.0.0/16 -j log-and-drop iptables -A FORWARD -i eth+ -s 172.16.0.0/12 -j log-and-drop iptables -A FORWARD -i eth+ -s 10.0.0.0/8 -j log-and-drop # Los paquetes que pertenezcan a una conexión ya establecida se aceptan iptables -A FORWARD -m state --state INVALID -j log-and-drop iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT # La cadena se transmite según el correspondiente paquete de origen iptables -A FORWARD -s $DMZ_ADDR -i $DMZ_IFACE -o $BAD_IFACE -j dmz-bad iptables -A FORWARD -o $DMZ_IFACE -j bad-dmz # El resto se ignora iptables -A FORWARD -j log-and-drop # ICMPs aceptados iptables -A icmp-acc -p icmp --icmp-type destination-unreachable -j ACCEPT iptables -A icmp-acc -p icmp --icmp-type source-quench -j ACCEPT iptables -A icmp-acc -p icmp --icmp-type time-exceeded -j ACCEPT iptables -A icmp-acc -p icmp --icmp-type echo-request -j ACCEPT iptables -A icmp-acc -p icmp --icmp-type echo-reply -j ACCEPT iptables -A icmp-acc -j log-and-drop # Cadena exterior -> interior # se aceptan correo, DNS, http(s) y SSH iptables -A bad-dmz -p tcp --dport smtp -j ACCEPT iptables -A bad-dmz -p udp --dport domain -j ACCEPT iptables -A bad-dmz -p tcp --dport domain -j ACCEPT iptables -A bad-dmz -p tcp --dport www -j ACCEPT iptables -A bad-dmz -p tcp --dport https -j ACCEPT iptables -A bad-dmz -p tcp --dport ssh -j ACCEPT iptables -A bad-dmz -p icmp -j icmp-acc iptables -A bad-dmz -j log-and-drop # Cadena interior -> exterior # se aceptan correo, DNS, http(s) y telnet iptables -A dmz-bad -p tcp --dport smtp -j ACCEPT iptables -A dmz-bad -p tcp --sport smtp -j ACCEPT iptables -A dmz-bad -p udp --dport domain -j ACCEPT iptables -A dmz-bad -p tcp --dport domain -j ACCEPT iptables -A dmz-bad -p tcp --dport www -j ACCEPT iptables -A dmz-bad -p tcp --dport https -j ACCEPT iptables -A dmz-bad -p tcp --dport telnet -j ACCEPT iptables -A dmz-bad -p icmp -j icmp-acc iptables -A dmz-bad -j log-and-drop # Cadenas para la propia máquina iptables -N bad-if iptables -N dmz-if iptables -A INPUT -i $BAD_IFACE -j bad-if iptables -A INPUT -i $DMZ_IFACE -j dmz-if # Interfaz externa # sólo se acepta SSH en esta máquina iptables -A bad-if -p icmp -j icmp-acc iptables -A bad-if -p tcp --dport ssh -j ACCEPT iptables -A bad-if -p tcp --sport ssh -j ACCEPT ipchains -A bad-if -j log-and-drop # Interfaz interna iptables -A dmz-if -p icmp -j icmp-acc iptables -A dmz-if -j ACCEPT
Unas pocas palabras sobre la calidad de servicio. Linux puede modificar el campo ToS ("Tipo de Servicio") y cambiar su valor para dar al paquete una prioridad distinta. Por ejemplo, el siguiente comando cambia los paquetes SSH salientes para mejorar la respuesta de las conexiones.
iptables -A OUTPUT -t mangle -p tcp --dport ssh -j TOS --set-tos Minimize-Delay
De la misma forma, para las conexines FTP puede usar la opción '--set-tos Maximize-Throughput' para mejorar la tasa de transferencia en detrimento de la interactividad de la sesión.
Ya está. Ahora conoce lo básico para configurar un sistema
eficiente de filtrado de paquetes. Sin embargo, tenga en cuenta
que un cortafuegos no es la panacea en lo que a seguridad se
refiere. Sólo es una preocupación más. Configurar un cortafuegos
no le exime de utilizar contraseñas fuertes, actualizar el sistema
con los últimos parches de seguridad, utilizar un sistema de detección
de intrusos, etc.
|
Contactar con el equipo de LinuFocus
© Vincent Renardias, FDL LinuxFocus.org |
Información sobre la traducción:
|
2003-05-14, generated by lfparser version 2.34