Pequeño cortafuegos con Linux

3 mayo 2015
Josep Ma Solanes 0

Continuando el tema de la entrada anterior sobre qué es un cortafuegos, en esta entrada propongo el montaje de un pequeño cortafuegos con Linux que nos puede salvar de alguna patata caliente en nuestra red si no tenemos un cortafuegos a mano.

Se trata de colocar una máquina física o virtual entre el enrutador (router) de Internet y la red local, a fin de que todo el tráfico hacia Internet y desde Internet pase por él. De esta manera se controla la publicación de puertos desde fuera hacia dentro y de dentro hacia fuera.

Ponerse en situación

Para seguir un ejemplo real, recupero el montaje de la entrada anterior donde se dispone de un servidor de correo electrónico interno con frontal web. Se da por supuesto que el enrutador redirige todo el tráfico TCP y UDP a la IP externa del cortafuegos (192.168.0.2/29). El objetivo final de la configuración es tener las siguientes reglas:

  • Tráfico desde Internet a la red interna. (outside)
    • Acceso al puerto TCP 443 (https) a la IP pública. Publicación del servicio https (TCP 443) del servidor de correo electrónico (192.168.1.12).
    • Acceso al puerto TCP 25 (smtp) a la IP pública. Publicación del servicio smtp (TCP 25) del servidor de correo electrónico (192.168.1.12).
  • Tráfico desde la red interna a Internet. (inside)
    • Bloqueo del protocolo smtp (TCP 25) para todos los equipos de la red interna (192.168.1.0/24, a excepción de la IP 192.168.1.12.
    • Acceso del protocolo smtp (TCP 25) al exterior por el servidor de correo electrónico (192.168.1.12). Para evitar spam de algún troyano.
    • Acceso a los puertos web (TCP 80) y web segura (TCP 443) para todos los equipos de la red.
    • Acceso a los puertos de DNS (TCP y UDP 53) y servidor de tiempo (UDP 123) para el controlador de dominio (192.168.1.11).
    • Bloqueo del resto de puertos de servicios (TCP y UDP del 1 al 1024) para el resto de equipos.

 

Para los más avanzados, al final de la entrada, se despliega una zona desmilitarizada.

  • Tráfico desde Internet a la zona desmilitarizada. (dmz)
    • Acceso al puerto TCP 80 (http) a la IP pública. Publicación del servicio http (TCP 80) del servidor web (192.168.2.11).
  • Tráfico desde la red interna a la zona desmilitarizada. (dmz)
    • Acceso desde la red interna a la IP 192.168.2.11 por los puertos TCP 80 (http), TCP 22 (ssh).
  • Tráfico desde la zona desmilitarizada a Internet.
    • Bloqueo de todo el tráfico de salida hacia Internet de la zona desmilitarizada (192.168.2.0/27).
Red interna conectada a Internet mediante un cortafuegos que también controla una zona desmilitarizada (DMZ).
Red interna conectada a Internet mediante un cortafuegos que también controla una zona desmilitarizada (DMZ).

Requerimientos

Para este montaje, como es obvio, se necesita un poco de infraestructura. Esta infraestructura se puede montar en un entorno virtual. En mi caso, el laboratorio funciona sobre Microsoft Hyper-V, sobre el propio equipo de trabajo basado en Microsoft Windows 8.1. A nivel de red, el entorno virtual dispone de tres conmutadores (switch) virtuales: red pública, red interna y zona desmilitarizada. El cortafuegos es una máquina virtual basada en la distribución CentOs 6.5 (ver la guía de instalación) que tiene tres tarjetas de red (red pública, red interna y zona desmilitarizada). Como cortafuegos se utiliza IPTABLES incluído en el núcleo del propio Linux.

En caso de no desplegar la zona desmilitarizada, obviar la tercera tarjeta de red.

Para hacer correctamente las pruebas es necesario disponer de una máquina con los puertos a tratar encendida en cada red (tráfico, interna y dmz). La red local (no la interna, si no la que tengo conectada actualmente a Internet) se considera la red de tráfico, que permite salir a lnternet real, el resto son conmutadores internos, sin vínculo con el exterior del entorno virtual, se consideran redes aisladas.

 

¡Ánimo, a configurar el cortafuegos!

Primero que todo, para no volvernos locos, comprobar que las tarjetas de red están conectadas a las redes que corresponden (interna y tráfico) y disponen de las IPs correctas. Con la instrucción ifconfig, se averigua esta información:

[root@firewall ~]# ifconfig
eth0 Link encap:Ethernet HWaddr 00:15:5D:75:21:13
 inet addr:192.168.0.2 Bcast:192.168.0.7 Mask:255.255.255.248
 inet6 addr: fe80::215:5dff:fe75:2113/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:302 errors:0 dropped:0 overruns:0 frame:0
 TX packets:50 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000
 RX bytes:52745 (51.5 KiB) TX bytes:6826 (6.6 KiB)

eth1 Link encap:Ethernet HWaddr 00:15:5D:75:21:14
 inet addr:192.168.1.1 Bcast:192.168.1.255 Mask:255.255.255.0
 inet6 addr: fe80::215:5dff:fe75:2114/64 Scope:Link
 UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
 RX packets:0 errors:0 dropped:0 overruns:0 frame:0
 TX packets:10 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:1000
 RX bytes:0 (0.0 b) TX bytes:636 (636.0 b)

lo Link encap:Local Loopback
 inet addr:127.0.0.1 Mask:255.0.0.0
 inet6 addr: ::1/128 Scope:Host
 UP LOOPBACK RUNNING MTU:16436 Metric:1
 RX packets:0 errors:0 dropped:0 overruns:0 frame:0
 TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
 collisions:0 txqueuelen:0
 RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)

La interfaz eth0 corresponde a la pata de tráfico, la externa. Y que la eth1 corresponde a la pata interna. Este punto es muy importante, recomiendo lanzar un ping a un equipo de cada lado para comprobar la conexión antes de continuar.

En caso de haber añadido la tercera pata, es posible que la interfaz eth2 no figure en el listado porque aún no está configurada (comprobarlo con ifconfig -a o bien con un ls /sys/class/net). La interfaz lo corresponde al propio equipo, el loopback, y por lo tanto no tiene efectos hacia el exterior.

El otro paso a dar antes de entrar a configurar el IPTABLES es permitir a Linux reenviar los paquetes. Hay que modificar del archivo /etc/sysctl.conf el parámetro net.ipv4.ip_forward para restablecerlo a 1 (permitir):

net.ipv4.ip_forward = 1

En caso de querer hacerlo sólo mientras no se reinicia el equipo:

echo 1 > /proc/sys/net/ipv4/ip_forward

Para evitar problemas de configuración del cortafuegos es una buena práctica hacer limpio de todas las posibles reglas:

iptables --flush
iptables --delete-chain
iptables --zero
iptables --table nat --flush
iptables --table nat --delete-chain

Creación de las políticas por defecto, que permiten el tráfico:

iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables --table nat -P PREROUTING ACCEPT
iptables --table nat -P POSTROUTING ACCEPT

Guardar la configuración y reniciar el servicio:

service iptables save
service iptables restart

Con lo que queda la configuración del cortafuegos bien limpia, pero recordar que está todo permitido. Listar las políticas del cortafuegos:

iptables -L -n
iptables -L -n -t nat

Deben aparecer las reglas en blanco, pero con el tráfico permitido por defecto):

[root@firewall ~]# iptables -L -n
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


# También la tabla de nat:
[root@firewall ~]# iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target prot opt source destination

Chain POSTROUTING (policy ACCEPT)
target prot opt source destination

Chain OUTPUT (policy ACCEPT)
target prot opt source destination

Permitir la navegación desde dentro hacia fuera

Empezamos a filtrar. Primero el acceso a los servicios locales, los podemos aceptar todos.

iptables -A INPUT -i lo -j ACCEPT

Acceso a la consola del servidor por SSH desde la red interna:

iptables -A INPUT -i eth1 -p tcp -m tcp --dport 22 -j ACCEPT

Se hace el enmascaramiento de la red interna, es decir, se sustituye la IP de la red interna por la IP de la red pública del cortafuegos para salir a Internet.

iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE

Forzar a cerrar el resto de puertos TCP y UDP del rango del 1 al 1024, reservados a servicios para ambas redes, la externa y la interna.

iptables -A INPUT -s 0.0.0.0/0 -p tcp --dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p udp --dport 1:1024 -j DROP

Se puede probar que el equipo de la red interna ya puede navegar por Internet. Ojo, navegar, no resolver pings que están bloqueados.

Limitando la salida a Internet

Pero queremos limitar los puertos de salida hacia Internet, sólo a navegación (http, https), consultas DNS y servidor de tiempo por el controlador de dominio (192.168.1.11) y envío de correo electrónico por el servidor correspondiente (192.168.1.12).

Las instrucciones son:

iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eth1 -p tcp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eht1 -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eth1 -p udp --dport 123 -j ACCEPT
iptables -A FORWARD -s 192.168.1.12 -i eth1 -p tcp --dport 25 -j ACCEPT

#Aseguremos que nadie más de la red pueda enviar correo electrónico por el puerto 25.
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 25 -j DROP

No obstante, deben estar por orden y si hemos creado anteriormente otras reglas éstas se añadirán al final, no está mal editar el archivo de configuración de las reglas:

vi /etc/sysconfig/iptables

Para añadir las reglas antes de las líneas de DROP (al editar el archivo de iptables directamente se obvia la palabra iptables de cada línea):

:OUTPUT ACCEPT
-A INPUT -i eth1 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT

-A INPUT -p tcp -m tcp --dport 1:1024 -j DROP
-A INPUT -p udp -m udp --dport 1:1024 -j DROP

Hay que reiniciar el servicio para aplicar las modificaciones:

service iptables restart

Ya se ha terminado de configurar la salida hacia Internet.

Recopilación de todas las instrucciones para permitir la navegación de dentro hacia fuera

Limitando el acceso a determinados puertos de salida a Internet.

iptables --flush
iptables --delete-chain
iptables --zero
iptables --table nat --flush
iptables --table nat --delete-chain
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables --table nat -P PREROUTING ACCEPT
iptables --table nat -P POSTROUTING ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -p tcp -m tcp --dport 22 -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eth1 -p tcp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eht1 -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eth1 -p udp --dport 123 -j ACCEPT
iptables -A FORWARD -s 192.168.1.12 -i eth1 -p tcp --dport 25 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 25 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p tcp --dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p udp --dport 1:1024 -j DROP
service iptables save
service iptables restart

Publicando servicios de dentro a Internet

Toca dar acceso al servidor de correo electrónico, por el protocolo smtp y web segura, que tenemos en la red interna desde el exterior. En la configuración anterior, hay que añadir las siguientes reglas:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to 192.168.1.12:25
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to 192.168.1.12:443

Recopilación de todas las instrucciones para permitir la navegación de dentro a fuera con publicación de puertos

Limitando el acceso a determinados puertos de salida y publicando diferentes servicios.

iptables --flush
iptables --delete-chain
iptables --zero
iptables --table nat --flush
iptables --table nat --delete-chain
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables --table nat -P PREROUTING ACCEPT
iptables --table nat -P POSTROUTING ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -p tcp -m tcp --dport 22 -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eth1 -p tcp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eht1 -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eth1 -p udp --dport 123 -j ACCEPT
iptables -A FORWARD -s 192.168.1.12 -i eth1 -p tcp --dport 25 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 25 -j DROP
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to 192.168.1.12:25
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to 192.168.1.12:443
iptables -A INPUT -s 0.0.0.0/0 -p tcp --dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p udp --dport 1:1024 -j DROP
service iptables save
service iptables restart

Configurando la zona desmilitarizada

Después de configurar la tarjeta de red del cortafuegos que pertenece a la zona desmilitarizada, la publicación de puertos es igual a tener el servidor en la red interna, sólo cambia la IP de destino:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to 192.168.2.11:80

Pero falta enmascarar la zona desmilitarizada para salir a Internet:

iptables -t nat -A POSTROUTING -s 192.168.2.0/27 -o eth0 -j MASQUERADE

Cerrar el acceso desde la zona desmilitarizada en la red interna:

iptables -A FORWARD -s 192.168.2.0/27 -d 192.168.1.0/24 -j DROP

Cerrar el acceso desde la zona desmilitaritzada al propio cortafuegos:

iptables -A INPUT -s 192.168.2.0/27 -i eth2 -j DROP

Recopilación de todas las instrucciones para permitir la navegación de dentro a fuera con publicación de puertos con una zona desmilitarizada

Limitando el acceso a determinados puertos de salida y publicando diferentes servicios ya sean en la red interna como en la zona desmilitarizada.

iptables --flush
iptables --delete-chain
iptables --zero
iptables --table nat --flush
iptables --table nat --delete-chain
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables --table nat -P PREROUTING ACCEPT
iptables --table nat -P POSTROUTING ACCEPT
iptables -A INPUT -i lo -j ACCEPT
iptables -A INPUT -i eth1 -p tcp -m tcp --dport 22 -j ACCEPT
iptables -t nat -A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
iptables -t nat -A POSTROUTING -s 192.168.2.0/27 -o eth0 -j MASQUERADE
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 80 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 443 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eth1 -p tcp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eht1 -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -s 192.168.1.11 -i eth1 -p udp --dport 123 -j ACCEPT
iptables -A FORWARD -s 192.168.1.12 -i eth1 -p tcp --dport 25 -j ACCEPT
iptables -A FORWARD -s 192.168.1.0/24 -i eth1 -p tcp --dport 25 -j DROP
iptables -A FORWARD -s 192.168.2.0/27 -d 192.168.1.0/24 -j DROP
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 25 -j DNAT --to 192.168.1.12:25
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j DNAT --to 192.168.1.12:443
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to 192.168.2.11:80
iptables -A INPUT -s 192.168.2.0/27 -i eth2 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p tcp --dport 1:1024 -j DROP
iptables -A INPUT -s 0.0.0.0/0 -p udp --dport 1:1024 -j DROP
service iptables save
service iptables restart

 

Fortificación con el cortafuegos de un servidor Linux

Un pequeño plus para cerrar la entrada.

En este caso interesa bloquear todos los puertos de la máquina y ir abriendo ¡los que se necesiten! Ojo con conexiones a consola remotas que os puede dejar sin conexión.

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

Habilitar el acceso por la tarjeta de loopback, es decir, que permite trabajar a «tuti pleni» el localhost (127.0.0.1):

iptables -A INPUT -i lo -j ACCEPT
iptables -A OUTPUT -o lo -j ACCEPT

Habilitar el acceso a la consola por SSH desde la red interna para poder manipular la configuración, sin necesidad de abrir la consola local:

iptables -A INPUT -i eth1 -p tcp -m tcp --dport 22 -j ACCEPT
iptables -A OUTPUT -o eth1 -p tcp -m tcp --sport 22 -m state --state RELATED,ESTABLISHED -j ACCEPT

Habilitar el acceso al servicio web desde la red interna y externa:

iptables -A INPUT -i eth1 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -o eth1 -p tcp -m tcp --sport 80 -m state --state RELATED,ESTABLISHED -j ACCEPT

iptables -A INPUT -i eth0 -p tcp -m tcp --dport 80 -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp -m tcp --sport 80 -m state --state RELATED,ESTABLISHED -j ACCEPT

A fin de permitir hacer actualizaciones o otros servicios en la propia máquina, hay que habilitar estas conexiones permitidas:

# Consultas a un servidor DNS (80.58.0.33)
iptables -A INPUT -s 80.58.0.33 -p udp -m udp --sport 53 -j ACCEPT
iptables -A OUTPUT -d 80.58.0.33 -p udp -m udp --dport 53 -j ACCEPT

# Consultas al servidor de tiempo pool.ntp.org (81.47.170.118)
iptables -A INPUT -s 81.47.170.118 -p udp -m udp --sport 123 -j ACCEPT
iptables -A OUTPUT -d 81.47.170.118 -p udp -m udp --sport 123 -j ACCEPT

# Navegación web HTTP
iptables -A INPUT -p tcp -m tcp --sport 80 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp --dport 80 -j ACCEPT

# Navegación web segura HTTPS
iptables -A INPUT -p tcp -m tcp --sport 443 -m state --state RELATED,ESTABLISHED -j ACCEPT
iptables -A OUTPUT -p tcp -m tcp --dport 443 -j ACCEPT

 

¿Te ha gustado el artículo? Lo puedes compartir en las redes sociales. También puedes dejar tu opinión, comentario o sugerencia. ¡Gracias!

Similar Posts by The Author: