Está en la página 1de 22

Tema 2.1: El cortafuegos.

6.1 Introducción.

Una de las medidas de seguridad perimetral más importantes, si no la más, es el cortafuegos


o firewall.

Un cortafuegos es un sistema que analiza los paquetes que entran por sus interfaces de red
y, basándose en un conjunto de reglas definidas por el administrador, toma una decisión
sobre qué hacer con cada uno de ellos, es decir, lleva a cabo una acción que en definitiva es
aceptarlo (dejarlo pasar) o rechazarlo (descartarlo).

Podemos afirmar que todos los routers son, en esencia, cortafuegos. La diferencia entre unos
y otros está en si su firmware pone a disposición del administrador (o no) la capacidad de
establecer reglas.

Por ejemplo, los routers domésticos, orientados a un público inexperto cuya única
preocupación es disponer de acceso a internet, incorporan un cortafuegos predefinido que
solo admite mínimas opciones de configuración.

Dichos cortafuegos básicos se basan en las siguientes reglas:

● Dejar salir cualquier paquete de la red interna (LAN) hacia la interfaz de red de internet
(WAN).

● Rechazar cualquier paquete proveniente de internet (WAN), excepto aquellos que


sean respuesta a una solicitud previa, es decir, pertenezcan a una conexión saliente
establecida en virtud de la regla anterior.

6.2 Conceptos previos.

Antes de profundizar en el estudio del cortafuegos de Linux, es necesario comprender varios


conceptos fundamentales.

6.2.1 Paquetes.

La transmisión de datos por las redes TCP/IP se realiza en forma de pequeños paquetes IP
(de aproximadamente 1,5 KB de máximo).

Un paquete siempre incluye una cabecera con la información necesaria para que los
dispositivos de red (routers y switches) sean capaces de entregarlo a su destino. El resto del
paquete, la carga o payload, está formado por los datos que se están transmitiendo.

Los datos que transportan los paquetes IP pueden ser de muchísimos tipos, pero todos se
transmiten dentro de paquetes IP.A veces se transmiten datos HTTP, otras veces datos FTP,
etc. Es decir, los paquetes IP contienen información codificada mediante otros protocolos que
están por encima en la pila de protocolos TCP/IP.
En la siguiente imagen vemos cómo un paquete HTTP, que tiene su propia cabecera, es el
payload de un paquete TCP; y este, a su vez, es el payload de un paquete IP. Es como si
enviamos un papel dentro de una carta, y la carta dentro de una caja; el destinatario abrirá la
caja, sacará el sobre, lo abrirá, y leerá el papel. Es lo que denominamos encapsulamiento.

El emisor (un navegador web) genera cl paquete HTTP, el sistema operativo lo encapsula en
un paquete TCP con información importante en su cabecera (puertos origen y destino, entre
otros), y este lo encapsula en un paquete IP con información igualmente importante
(direcciones de origen y destino, por ejemplo).

El paquete IP resultante es entregado a la tarjeta de red para que lo envíe. Al llegar al equipo
de destino, este va "desempaquetando" en el sentido contrario, hasta encontrarse con el
paquete HTTP original, que es entregado al proceso servidor web.

En esta figura anterior, podemos ver los campos que contiene la cabecera de cualquier IP.
No vamos a entrar aquí en el cometido de cada uno de ellos, pero sí queremos hacer mención
de tres muy importantes de los que haremos uso en los cortafuegos:

● Protocolo: El campo "protocolo" contiene un código que hace referencia al protocolo


utilizado en el payload, que suele ser TCP, UDP o ICMP.

● Dirección IP de origen y destino: Los campos "dirección IP de origen" y "dirección IP


de destino" indican las direcciones IP de los equipos remitente y destinatario,
respectivamente; dichos campos pueden ser alterados por los muters en
determinadas ocasiones como, por ejemplo, cuando hacen uso del protocolo NAT,
como vimos en el tema anterior.

6.2.2 Reglas y acciones.

La configuración de un cortafuegos se realiza estableciendo reglas. Una regla estipula,


para cada paquete, que acción u objetivo (target) debe tomarse en función de diversos
factores.
Las acciones posibles son:

● ACCEPT: aceptar el paquete.


● REJECT: rechazar el paquete. Haciendo uso del protocolo ICMP, se le envía un
mensaje al emisor para advertirle de que el paquete ha sido rechazado.
● DROP: descartar el paquete. No se envía ningún tipo de aviso al emisor.

En realidad hay más acciones posibles, pero de momento tenemos suficiente con estas tres.
La única diferencia entre REJECT y DROP reside en el aviso al emisor.

Si usamos REJECT, el emisor verá un mensaje de error; si usamos DROP, el emisor quedará
esperando una respuesta que nunca llegará. En la mayoría de las ocasiones se utiliza DROP,
pues se trata de evitar ataques, no de ser educado con los atacantes. REJECT se usa
principalmente para rechazar conexiones HTTP/HTTPS, de modo que el usuario vea el
mensaje de error en pantalla.
Las condiciones sobre las cuales una regla toma su decisión consisten en comprobaciones
sobre:

● El contenido de uno o más campos de la cabecera del paquete, como dirección de


origen o destino, puerto de origen o destino, protocolo utilizado (TCP, UDP, ICMP),
campos específicos de las cabeceras de esos protocolos, etc.

● La interfaz de red por la que entra o sale el paquete.


● La dirección MAC de origen.

● El estado de la conexión (tratamos este concepto más adelante).

● Si la dirección de origen (o la de destino) pertenece a una determinada lista de


direcciones (de este modo el administrador puede crear una lista negra o blacklist).

Así, podríamos definir una regla como la siguiente: "Si el paquete entra en el router por eth0,
la dirección de origen es 192.168.1.23, el protocolo es TCP y el puerto de destino es 80,
entonces ACCEPT".

Se pueden crear reglas sin condiciones, solo con una acción. Dicha regla se aplicará a todos
los paquetes (es decir, equivale en programación a una instrucción "if TRUE then").

Pero cuando una regla contiene condiciones, se deben cumplir todas las especificadas (el
equivalente en este caso sería un "if cond1 AND cond2 AND ... then").

Cuando se cumple la condición de una regla, se aplica su acción y no se continúa con la


siguiente regla, se finaliza la cadena. También es posible, aunque pueda parecer absurdo,
crear reglas con condición pero sin acción: se utilizan con fines estadísticos.

6.2.3 Cadenas y tablas.

Las reglas de un cortafuegos se agrupan en cadenas (chairas). Es un término que hace


referencia a que las reglas están encadenadas una detrás de la otra, como los pasos
sucesivos de un algoritmo. Todo cortafuegos dispone de tres cadenas predefinidas:

● INPUT: estas reglas se aplican a los paquetes entrantes cuyo destino es el propio
router.
● OUTPUT: estas reglas se aplican a los paquetes salientes (el origen es el router). •
● FORWARD: estas reglas se aplican a los paquetes entrantes cuyo destino no es el
router, es decir, son paquetes que deben ser enrutados y, por tanto, volver a salir.

La figura anterior con el organigrama, representa una cadena y, como puede verse, cada
cadena tiene una acción por defecto, que es la que se aplica a los paquetes que no se han
ajustado a ninguna otra anterior.

Esta regla especial se denomina política de la cadena (policy).


Todos los equipos Linux vienen con un cortafuegos cuyas cadenas INPUT, OUTPUT y
FORWARD están vacías (no contienen reglas) y tienen como política la acción ACCEPT. Es
decir, un equipo Linux recién instalado no descarta nunca ningún paquete, ¡es como si no
tuviera cortafuegos!, todo lo contrario que un equipo Windows.

Retomando el ejemplo del apartado anterior ("Si el paquete entra en el router por eth0, la
dirección de origen es 192.168.1.23, el protocolo es TCP y el puerto de destino es 80,
entonces ACCEPT"), vemos que esta regla tendría sentido en las cadenas INPUT o
FORWARD, no en OUTPUT.
Las cadenas, a su vez, se agrupan en tablas. Es una forma de clasificar las cadenas según
el uso que el kernel hace de ellas. Las tres cadenas antes mencionadas forman parte de la
tabla filter, pues el objetivo de estas cadenas es filtrar los paquetes (aceptar unos y rechazar
otros). Las tablas existentes son las siguientes:

● Filter: para filtrar paquetes.


● Nat: las cadenas de esta tabla sirven para decidir a qué paquetes se les aplica el
protocolo NAT de traducción de direcciones. Las reglas de estas cadenas pueden
tener las acciones MASQUERADE (Source NA7) o DNAT (Destination NAT), como
luego veremos.
● Mangle: las cadenas de esta tabla permiten modificar los paquetes, alterando algún
campo o añadiendo alguna marca.
● Raw: las cadenas de esta tabla se aplican antes que cualquier otra tabla, cuando los
paquetes aún están sin alterar y sin clasificar según conexión (raw significa 'crudo').

Por lo tanto, cuando un paquete entra al kernel (desde la red u originado por un proceso local)
comienza un itinerario por las diferentes cadenas, esperando a que en alguna de ellas haya
una regla que decida qué hacer con él.

Si la acción es ACCEPT, el paquete continúa su camino por el kernel, pasando a la siguiente


cadena disponible; si la acción es DROP o REJECT, el paquete se elimina y no continúa su
camino.

6.2.4 Cadenas definidas por el usuario.

Es fácil que una cadena como FORWARD (de la tabla filter) contenga tantas reglas que
resulte complicado, incluso para el propio administrador, saber cuál es el cometido de cada
una de ellas.

Para facilitar la organización de las reglas, es posible crear cadenas definidas por el usuario,
formando algo parecido a lo que en programación sería llamar a una función.

Cuando un paquete “salta” a una cadena definida por el usuario (acción JUMP), y la recorre
entera sin saber que se le aplique ninguna regla, el control vuelve a la cadena original,
continuando por la regla siguiente a la que realizo el salto.

Podemos utilizar la acción especial RETURN para regresar de la cadena definida por el
usuario en cualquier regla que no sea la última.
Dicho de otro modo, las cadenas definidas por el usuario no tienen política por defecto,
siempre devuelven el control a la cadena desde la que fueron llamadas; o, si se prefiere, se
puede decir que la política por defecto siempre es RETURN.

Es importante tener en cuenta que:

● Las cadenas definidas por el usuario son una forma excelente de organizar nuestro
firewall y hacerlo más fácil de leer.

● También son muy útiles para no duplicar reglas que van a ser utilizadas en dos
cadenas de la misma tabla (por ejemplo, en INPUT y FORWARD).

6.2.5 Seguimiento de conexiones.

El seguimiento de conexiones o conecction tracking es la capacidad que tienen los


cortafuegos de identificar conexiones entre dos equipos memorizarlas en el kernel para
clasificar los paquetes según aquella a la que pertenecen.

Una conexión queda definida por:

● Protocolo utilizado.
● IP: puerto origen <-> IP: puerto destino.

Es decir, todos los paquetes que tengan los mismos valores en estos cinco campos
pertenecen o pueden pertenecer a la misma conexión.
El cortafuegos debe memorizar estos valores de todos los paquetes entrantes para
comprobar si cada uno de ellos pertenece a una conexión ya abierta o es el primero de una
nueva. Pam dick, el kernel asigna un estado (state) a todos los paquetes:

● INVALID: el paquete no es considerado válido por algún motivo, pero aun así se le
deja pasar. Lo normal es rechazar (DROP) siempre este tipo de paquetes: aparte de
ser inservibles pueden tratarse de parte de un ataque de denegación de servicio.
● NEW: El paquete está iniciando una nueva conexión.
● ESTABLISHED: el paquete pertenece a una conexión ya abierta.
● RELATED: se ha creado una nueva conexión (normalmente consistente en un Único
paquete ICMP) a partir de una conexión ya establecida.

Un cortafuegos capaz de identificar y memorizar conexiones abiertas se denomina stateful


firewall. En caso contrario, recibe el nombre de stateless firewall.

El estado de un paquete es muy importante a la hora de definir las reglas de un cortafuegos,


ya que gracias al estado podemos fijarnos simplemente en los paquetes con estado NEW
para tomar nuestras decisiones, ahorrándole a la CPU del router el procesamiento de los
demás paquetes, que son la mayoría. Es decir, las cadenas INPUT y FORWARD siempre
deberían tener DROP como política por defecto y empezar por las dos reglas siguientes:

● Si el estado del paquete es INVALID -, DROP.


● Si el estado del paquete es ESTABLISHED o RELATED —> ACCEPT.
A continuación, todas las reglas que necesitemos para permitir los accesos que deseemos:

● Si el paquete entra por eth0, la dirección de destino es la del servidor web, el protocolo
es TCP y el puerto destino es 80 —> ACCEPT.
● Si el paquete... etc... etc... -' ACCEPT.

En estas últimas reglas, el estado de los paquetes siempre será NEW y, por tanto, no hace
falta comprobarlo explícitamente. Esto queda esquematizado en la figura siguiente.

6.2.6 NAT y MANGLE.

Para aclarar la utilidad de las tablas nat y mangle recurriremos a la empresa de ejemplo cuya
topología queda expuesta en la figura 6.8.
La tabla nat existe, como su nombre indica, para poder aplicar el protocolo NAT. Según la
figura, la LAN se comunica con el exterior a través del cortafuegos. Dado que la LAN utiliza
un direccionamiento privado, es necesario realizar NAT para poder comunicarse con el
exterior.

Tal y como queda reflejado en la figura 6.5, la cadena PREROUTING de la tabla nat es, por
tanto, el lugar adecuado para realizar SNAT (acción MASQUERADE), y, de hecho, ese es su
cometido.

Del mismo modo, la cadena POSTROUTING sirve para realizar DNAT (acción DNAT).

La tabla mangle (mangle= deformar, machacar) se utiliza para marcar los paquetes y,
posteriormente, utilizar esa marca en otras cadenas para algún cometido. Por ejemplo, si nos
fijamos en la figura 6.8, podríamos marcar los paquetes con valores diferentes según entren
al cortafuegos por eth1, eth2 o eth3.

Después, podríamos darle prioridad a los paquetes que salen por eth0 (es decir, hacia
internet) según su marca, de forma que el servidor tenga mayor prioridad para navegar
respecto a los equipos, y estos respecto a los dispositivos móviles.
Esta forma de priorizar un tipo de tráfico respecto a otro es lo que se denomina calidad de
servicio (QoS, Quality of Service), pero se escapa de los objetivos de este libro. Por lo tanto,
no volveremos a hablar de la tabla mangle.

6.3 Iptables.

La parte del Kernel de Linux encargada de la manipulación de los paquetes de red se llama
netfilter. Para configurarlo, mediante la creación de reglas, se utiliza el comando iptables.

Este comando necesita, lógicamente, permisos de root.

6.3.1 Añadir reglas.


La sintaxis de iptables para añadir una regla es la siguiente:

● Si se omite -t, iptables actúa sobre la tabla filter (¡ojo con esto!).
● El parámetro -A significa añadir la regla al final de la cadena <cadena>. Para ubicarla
en una posición concreta es necesario utilizar -L <num> (insertar) en lugar -A.
● El resto de parámetros sirve para definir las condiciones que debe cumplir el paque-
te para que se le aplique la <acción>. Deberán cumplirse todas las condiciones para
que se aplique la acción, la cual puede ser cualquiera de las predefinidas (ACCEPT,
DROP, etc.) o el nombre de una cadena definida por el usuario para saltar a ella (-j
viene, precisamente, de jume, 'salta?).

Veamos un ejemplo: cómo añadir una regla que sirva para detectar los paquetes entrantes
(al router), de protocolo TCP, que se dirigen al puerto 80 y que provienen de la red
90.100.21.0/24 para descargarlos.

Observa que hay un parámetro que comienza con doble guion. En el mundo Linux es muy
habitual que los parámetros se puedan escribir de dos formas: la corta (un guion) y la larga
(doble guion). Por ejemplo, el parámetro -j se podría escribir también como --jump.

Ten presente también que ciertos parámetros están permitidos solo si vienen precedidos de
otro concreto. En el ejemplo que nos ocupa, solo podemos incluir el parámetro que define el
puerto de destino (--dport) si previamente hemos especificado que se trata del protocolo TCP
(-p).

Conforme escribimos comandos iptables -A o iptables -I, las reglas entran en funcionamiento
al instante. Esto puede ser peligroso pues, si nos confundimos al escribir una regla
podríamos, incluso, llegar a bloquearse a nosotros mismos (esto le puede ocurrir a un
administrador despistado si se conecta remotamente por SSH a un sistema para hacer
cambios en el cortafuegos y, sin quererlo, añade una regla que le corta el acceso a sí mismo).

Por si esto fuera poco, las reglas de iptables se pierden al apagar el sistema: en el siguiente
inicio hay que volver a definirlas. Es decir, no son persistentes.

6.3.2 Persistencia de las reglas.

Para evitar los problemas descritos al final del apartado anterior existen dos comandos que
nos permiten guardar las reglas de iptables en un fichero de texto para así poder leerlas de
nuevo en el arranque, haciéndolas así persistentes. Se trata de iptables-save e iptables-
restore.
El primero de ellos vuelca en la salida la totalidad de las reglas de netfilter, en un formato que
tanto iptables restore como cualquier administrador es capaz de entender.
Para guardar el contenido de nuestro cortafuegos escribiremos (el nombre del fichero es
indiferente):

A partir de ese momento, será posible añadir, borrar, cambiar o reordenar las reglas editando
el fichero generado y ello no tendrá ningún efecto en el sistema hasta que lo ejecutemos:

Pero solo con lo anterior no hemos conseguido que nuestras reglas sean persistentes, pues
estaríamos obligados a ejecutar manualmente el comando iptables-restore tras cada reinicio
del sistema.

Ejemplo práctico

Veamos una forma de ejecutarlo de forma automática, es decir, de conseguir completamente


la persistencia.

1. Lo primero vamos a crear el fichero /etc/firewall.rules con las reglas actuales de


nuestro sistema:
2. Creamos un script de inicio /etc/network/if-pre-up.d/firewall con el siguiente contenido:

3. Creamos el script de cierre /etc/network/if.down.d/firewall con el siguiente contenido:

4. Cada vez que queramos hacer un cambio en nuestro cortafuegos, podemos editar el
fichero de reglas y aplicarlas a continuación con iptables-apply:

5. No hay que olvidar hacer ejecutables ambos ficheros usando:


chmod +x <fichero>.

En realidad, los scripts que acabamos de crear no se ejecutan al inicio o cierre del sistema,
sino al habilitar o deshabilitar el servicio de red del kernel, lo cual ocurre siempre en los
reinicios del sistema, pero también puede ocurrir en más ocasiones.

¿Qué aspecto tiene un fichero de reglas generado por iptables-save? Si ejecutamos dicho
comando en un cortafuegos en blanco, obtendremos el siguiente volcado:

La primera línea indica que, a continuación, se describen las cadenas de la tabla filter. Las
siguientes tres líneas indican las políticas por defecto de cada cadena.
La última línea ordena (a iptables-restore) que se deben aplicar las nuevas reglas. Si
hubiésemos ejecutado iptables-save tras haber añadido la regla del ejemplo del apartado
6.3.1, el resultado sería:
Como se puede observar, la sintaxis de las reglas equivale a la del comando iptables, pero
sin anteponer iptables, y obviando los parámetros -t (tabla) y -A (cadena), pues ya quedan
explícitos en las líneas predecesoras.

La opción -v añade información muy interesante a las reglas, al ser un contador de paquetes
a los cuales se ha aplicado cada regla. Otro parámetro útil que podemos añadir a los dos
anteriores es --line-numbers, cuyo nombre es suficientemente explicativo.

6.3.3 Parámetros de iptables más utilizados.

En la siguiente tabla, vamos a ver todos los parámetros del comando iptables:
A) Extensiones de iptables.

Aparte de los parámetros antes indicados, iptables puede analizar los paquetes con mucho
mayor detalle si se utilizan las extensiones. Las extensiones son, simplemente, parámetros
adicionales proporcionados por módulos de netfilter.

Para hacer uso de esos parámetros extra, debemos especificar el módulo deseado con el
parámetro -m. Por ejemplo, el módulo comment nos permite añadir un comentario a cada
regla de nuestro cortafuegos con la extensión --comment (algo muy recomendable):

Las extensiones solo pueden utilizarse tras especificar el módulo al que pertenecen. Si se
incluye una extensión sin especificar el módulo, iptables hará uso (si es posible) del módulo
del protocolo utilizado en la regla (-p/--protocol).
Se entenderá mejor con un ejemplo, los dos siguientes comandos son equivalentes:

En el primero de ellos, el parámetro —dport no es conocido por iptables, por lo que busca en
el módulo tcp (indicado en el parámetro -p), si este dispone de una extensión con ese nombre.

De no ser así, el comando devuelve error (unknown option). Unas pocas extensiones no
necesitan ser precedidas por el parámetro -m, por lo que pueden ser tratadas como
parámetros originales de iptables. Es el caso de —state, del que hemos hablado hace poco.

Las extensiones son, ciertamente, las que hacen de iptables un cortafuegos tan potente. Casi
cualquier aspecto imaginable de un paquete puede ser comprobado en una regla gracias a
la existencia de alguna extensión diseñada para tal fin.

Del mismo modo que existen extensiones para agregar filtros (llamadas match extensions),
como las mencionadas hasta ahora, también existen extensiones que añaden nuevas
acciones disponibles para el parámetro -j, como es el caso de la extensión reject que añade
la acción REJECT que ya conocemos.

En el resto del tema, se hará uso de diversas extensiones: cualquier parámetro que no haya
sido explicado hasta este momento es porque pertenece a una extensión.

B) Control de conexiones.

El módulo state permite filtrar los paquetes en virtud del estado de la conexión a la que
pertenecen, que ya sabemos que puede ser NEW, ESTABLISHED, RELATED o INVALID.

Por ejemplo, para aceptar los paquetes entrantes pertenecientes a conexiones ya conocidas,
utilizaremos la siguiente regla:

C) Listas de direcciones.

El módulo set nos permite verificar si la dirección IP de origen o de destino de los paquetes
pertenece a una lista de direcciones.

De este modo, es posible rechazar paquetes provenientes de equipos pertenecientes a una


lista negra (blacklist); del mismo modo, también podemos aceptar sin rechistar cualquier
conexión iniciada por equipos pertenecientes a una lista blanca (whitelist):
La extensión —match-set, como podemos ver, necesita dos argumentos:

● El primero es el nombre de la lista de direcciones IP que vamos a utilizar;


● El segundo es la dirección del paquete que vamos a buscar en dicha lista, en nuestro
caso tanto la dirección de origen (src) como la de destino (dst) del paquete.

Antes de utilizar reglas que hagan uso de listas de direcciones, es necesario crearlas con el
comando ipset (apt-get install ipset).

Existen distintos tipos de listas de direcciones, cada una optimizada en memoria y velocidad
de procesamiento para diferentes usos. Por ejemplo, no es lo mismo una lista que almacena
direcciones IP individuales que una lista que deba almacenar rangos o subredes.

Una vez creada una lista de direcciones con ipset, podemos añadir manualmente direcciones
con el propio comando ipset o dejar que sea iptables quien lo haga gracias al target SET.

● Veamos unos ejemplos de uso de este comando:

1. Línea 1: Crea una lista de direcciones IP llamada blacklist de tipo hash (hash:ip). Las
direcciones que se añadan a esta lista permanecerán en ella 60 minutos (timeout
3600). Para cada dirección añadida, será posible almacenar un comentario
(comment).

2. Línea 2: añade una dirección IP a la blacklist, pero especificando que nunca caducará
(timeout 0); si no hubiésemos indicado esta opción, la IP sería eliminada de la lista
automáticamente al transcurrir 60 minutos, como quedó establecido en el comando
anterior.

3. Línea 3: crea otra lista de direcciones (se pueden crear tantas como se deseen)
denominada whitelist; en este caso las direcciones añadidas no caducarán nunca,
excepto que se indique lo contrario al incluirlas en la lista con el parámetro timeout.
4. Línea 4: añade toda una subred (192.168.0.0/24) a la whitelist, lo que internamente
hace que ipset incluya automáticamente en la lista las 256 direcciones resultantes.
5. Líneas 5 y 6: lista el contenido de la blacklist y comprueba si la IP 10.0.0.5 aparece
en dicha lista.

Las listas de direcciones, al igual que las reglas del cortafuegos, tampoco son persistentes.
Para que lo sean deberemos editar los scripts descritos en el apartado 6.3.2.

En concreto, editaremos el fichero /etc/network/if-pre-up.d/firewall para que tenga el siguiente


contenido:

Es importante cargar primero las listas, para que no se produzca ningún error al cargar las
reglas del cortafuegos: no puede haber una regla que haga mención a una lista de direcciones
inexistente.

También debemos modificar el fichero /etc/network/if.down.d/firewall:

6.3.4 Un cortafuegos mínimo.

A continuación mostramos lo que debería ser el conjunto mínimo de reglas que siempre
debemos considerar en todo equipo de escritorio Linux (enumeramos las líneas para poder
hacer referencia a ellas, pero esa numeración no forma parte del fichero /etc/firewall.rules).

No son exactamente las reglas que nos pueden servir en un cortafuegos empresarial
(obsérvese la ausencia de reglas en la cadena FORWARD), pero nos valen desde un punto
de vista didáctico.

Por brevedad se omiten los comentarios (-m comment), a pesar de que es una práctica muy
recomendable.
● Líneas 2 a 4: establecemos las políticas de cada cadena. Rechazamos los paquetes
entrantes y los enrutados; aceptamos siempre los paquetes que surjan del propio
router.
● Línea 5: rechazamos paquetes marcados como INVALID; la acción REJECT devuelve
un mensaje de error mediante el protocolo ICMP, en concreto el mensaje "Port
unreachable".
● Línea 6: aceptamos las conexiones ya conocidas. Dicho de otro modo, admitimos
paquetes entrantes que pertenezcan a conexiones salientes.
● Línea 7: aceptamos todo lo que provenga de la interfaz de loopback, es decir,
127.0.0.1.
● Línea 8: aceptamos las conexiones TCP a los puertos 80 y 443 (esto solo tiene sentido
si tenemos instalado un servidor web configurado para servir páginas HTTP y HTTPS).
Obviamente esto no es lo habitual, solo lo incluimos aquí con fines didácticos.
● Líneas 9 a 14: aceptamos solo algunos de los tipos de mensaje ICMP, entre ellos el
echo-reply, necesario para que nuestro equipo responda al ping. No debemos
bloquear sin más el protocolo ICMP, pues nuestra red dejaría de funcionar. Y es que,
aunque ICMP puede ser utilizado para atacar sistemas, es un protocolo necesario en
las redes TCP/IP.
● Línea 15: impedimos la salida de paquetes marcados como INVALID. Esto nunca
debería ocurrir, pero no estorba tener esa regla en OUTPUT.

Para aplicar estas reglas, como ya sabemos, solo tendremos que ejecutar el comando:

6.3.5 Un cortafuegos empresarial mínimo.


Un cortafuegos empresarial tiene dos cometidos, como router que es: hacer NAT para que
los equipos de la red interna puedan salir a internet, y rechazar cualquier acceso a la red
interna desde el exterior, exceptuando las conexiones a servicios que deban ser visibles
desde internet.

Volviendo al ejemplo de la figura 6.8, tenemos un cortafuegos configurado de la siguiente


forma:

● Con una IP pública en su interfaz eth0, la cual está conectada a la compañía


proveedora de internet (ISP). Ha sido dicha compañía ISP la que le ha comunicado al
administrador del sistema la IP que debía usar para poder conectarse a internet.

● Con IP privadas en el resto de sus interfaces web. Cada una de ellas representa una
subred diferente: eth1 está en la subred 192.168.0, eth2 en la 192.168.1 y eth3 en la
192.168.2. Esto es perfecto para evitar tráfico innecesario entre redes (los paquetes
broadcast, por ejemplo), aun permitiendo la comunicación entre redes (los PC pueden
acceder al servidor web) pues, a fin de cuentas, para eso sirve un router.

● Al ser subredes separadas, no sólo en el direccionamiento, sino en las interfaces de


red del cortafuegos a las que están conectadas cada una, es fácil añadir una regla
que impida, por motivos de seguridad, la comunicación entre los equipos inalámbricos
y el servidor.

Las reglas que permiten configurar nuestro cortafuegos para esta empresa son las siguientes:
Vamos a ir explicando cada una de las líneas.

● Línea 1: indica que, a continuación, estamos definiendo las cadenas de la tabla nat.
● Líneas 2 a 4: política por defecto en las tres cadenas pertenecientes a la tabla nat.
Siempre se deben dejar en ACCEPT (¿adivinas qué efecto tendría cambiarlas a
DROP?).
● Línea 5: aquí estamos indicando al router que debe aplicar el protocolo NAT para todo
el tráfico saliente a internet (-o eth0). La acción MASQUERADE hace referencia al
enmascaramiento de la dirección IP de origen, por lo que en algunos cortafuegos
profesionales aparece con el nombre de SNAT (Source NA7).

Recurrimos a la figura 6.5 para comprender en qué momento se ejecuta esta regla.

● Línea 6: esta regla realiza el efecto contrario a SNAT, le indica al muter que debe
efectuar DNAT (Destination NAT) hacia un equipo interno, lo que en muchos muters
aparece bajo el epígrafe "redirección de puertos".

Cualquier paquete proveniente de internet (-i eth0), con protocolo TCP (-p tcp) y cuyo
destino sea el puerto 80 (--dport 80), seguramente se trata de una conexión HTTP,
pero el cortafuegos no puede atenderla, por lo que debe redirigirla al servidor web
(cuya dirección es la 192.168.0.100 según la figura 6.8).

● Línea 7: idéntica a la anterior, pero fijándose en el puerto 443, el utilizado por HTTPS.

● Línea 8: es necesario un comando COMMIT para cada tabla. Este guarda todas las
reglas anteriores en la tabla NAT, eliminando las que pudiera contener anteriormente.

● Línea 9: a partir de ahora vamos a configurar las cadenas de la tabla filter.

● Líneas 10 a 12: definimos las políticas de cada cadena. Observa que la política de
FORWARD es ACCEPT ya que, ahora sí, porque ya se trata de un router.
● Línea 13: el parámetro -N (—new-chain) permite crear una cadena definida por el
usuario. En nuestro caso la llamamos FILTRA ICMP. ¿Con qué motivo creamos una
cadena definida por el usuario? Para no tener que repetir las mismas reglas en las
cadenas INPUT y FORWARD y, de paso, ofrecer una lectura más limpia del conjunto
de las reglas del cortafuegos.

● Líneas 14 y 15: nuestras dos reglas básicas para aceptar o rechazar conexiones
dependiendo de que sean conocidas o no válidas. Utilizamos las extensiones state y
reject: la primera nos permite usar el parámetro --state mientras que la segunda nos
permite usar la acción REJECT y el parámetro --reject-with.

● Línea 16: permitimos los paquetes que entran en el router provenientes del propio
router, haciendo uso de la interfaz de red virtual loopback (-i lo).

● Línea 17: salta a la cadena definida por el usuario FILTRA ICMP. Si un paquete no
cuadra con ninguna de las reglas de FILTRA ICMP, la ejecución seguiría por la
siguiente línea. Lo que ocurre es que ya no hay más reglas en la cadena INPUT, por
lo que se aplicaría la política por defecto (DROP, en virtud de la línea 10).

● Líneas 18 a 20: Las mismas reglas que nos sirven para proteger el router (cadena
INPUT) nos sirven para proteger el salto de paquetes entre redes (cadena
FORWARD).

● Línea 20: volveremos a hacer uso de la cadena definida por el usuario FILTRA ICMP,
ya que deseamos permitir el paso de los mismos tipos de mensaje ICMP y rechazar
el resto.

● Línea 21: una vez que las líneas 6 y 7 han modificado los paquetes HTTP/HTTPS con
DNAT, el router debe enrutarlos a su nuevo destino (el servidor web en
192.168.0.100).

La política por defecto de la cadena FORWARD es ACCEPT, por lo que no


deberíamos preocuparnos por estos paquetes, pues van a ser aceptados.

Sin embargo, la línea 22 veremos cómo define una regla que corta el paso a todos los
intentos de conexión que vengan del exterior. Por eso debemos definir antes, en esta
línea una regla específica para aceptar los paquetes que van a nuestro servidor web.

● Línea 22: Como acabamos de explicar, esta regla impide el enrutamiento de


conexiones nuevas (recuerda que desde la línea 20, solo noes estabamos fijando en
paquetes con estado NEW) desde el exterior (-i eth0) a cualquier subred local (! -o
eth0).

● Línea 23: impedimos que los paquetes provenientes de la red WIFI (-i eth3) sean
enrutados a las otras subredes de la empresa, permitiendo solo el acceso a internet (!
-o eth0 -j DROP).
● Línea 24: la cadena OUTPUT tiene como política por defecto la acción ACCEPT. Con
esta regla solo eliminamos los paquetes que envía el router y él mismo marca como
no válidos. Lo normal es que el contador interno de esta regla siempre permanezca a
cero.

● Líneas 25 a 30: reglas que sirven para aceptar los tipos de mensaje ICMP que
queremos permitir. Las líneas 25 y 26, por ejemplo, dejan pasar los mensajes usados
por ping.

● Línea 31: como puede verse, es una regla que no tiene condiciones, solo la acción
DROP. Es decir, rechaza todos los paquetes que llegan hasta aquí, sin excepción. Por
lo tanto, la cadena FILTRA ICMP nunca regresa a la cadena que la llamó (INPUT o
FORWARD, en nuestro caso). Es la regla que rechaza el resto de mensajes ICMP
que no hemos aceptado con las anteriores.

● Línea 32: este COMMIT es el que guarda en el cortafuegos las reglas de la tabla filter.

También podría gustarte