• Suscríbete al Feed Espacio Linux
  • Suscríbete al Feed por Email
  • Sigue a Espacio Linux en Identi.ca
  • Espacio Linux también en Facebook
  • Sigue a Espacio Linux en Twitter
  • Sigue a Espacio Linux en Google +
          Iniciar sesión | Registrarse

El filtrado de paquetes con Linux

Uno de los mejores medios para evitar los intentos de intrusión sigue siendo filtrar todas las entradas a la red que no se utilicen. Esta tarea habitualmente la desempeña una máquina que hace las veces de “firewall” (cortafuegos).
En este artículo, detallaremos los principios básicos para la implementación y configuración de dicho sistema.

¿Pasarela, Proxy-Arp o Puente Ethernet?

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.


Localización del cortafuegos en la red
Localización del cortafuegos

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

Reglas básicas de filtrado

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.

Netfilter

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.

Ejemplo de configuración

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.


Flujo de paquetes en las cadenas estándar


Flujo de paquetes

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 ms

Ahora, 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.

Referencias

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.


Temas:
Documentación, Seguridad


Etiquetas:
, ,

Feed Espacio LinuxSi este artículo ha sido de tu interés, considera hacer un comentario o suscribirte al feed para que te enteres de nuevos artículos a través de tu lector de noticias o email.

Acerca del autor

Publica un comentario

Puedes usar estas etiquetas XHTML: <a href="" title=""> <abbr title=""> <acronym title=""> <blockquote cite=""> <code> <em> <strong>