martes, 18 de mayo de 2010

Un vistazo a Iptables con DMZ


Revisando el baúl de los recuerdos me encontré con algunos trabajos escolares, y me se me ocurrió que era buena idea comentar alguno de ellos. Definitivamente uno de mis favoritos es iptables, y en este ejemplo hacemos una implementación de esas reglas para una arquitectura con DMZ.

Les voy a compartir un script, que lo que hace es activar un firewall usando iptables y que a la vez tiene finalidad de ayudarnos a protegernos a nivel de capa de red y transporte. El único requerimiento es tener instalado awk, e iptables en linux.

#!/bin/bash
#Re-adaptado por:
#Martin Edmundo Barriga Orozco

#Revisamos la dependencia de AWK
awk --version > /dev/null
if [ "$?" != "0" ]; then
echo "Se requiere AWK para continuar"
exit 1
fi

echo "Preparando interfaces..."
echo 1 > /proc/sys/net/ipv4/ip_forward

#Interfaces de red que usamos para la red LAN, DMZ e Internet
if_lan="eth1"
if_dmz="eth2"
if_pub="eth0"

#Direcciones que tenemos en cada interface
ip_pub="10.27.46.145"
ip_lan="172.16.1.254"
ip_dmz="192.168.1.254"

#Direcciones IPs conocidas.
web_server="192.168.1.1"
mail_server="192.168.1.3"
dhcp_server="192.168.1.129"
dns_server="192.168.1.2"

id_lan="172.16.0.0/16"
id_dmz="192.168.1.0/24"

#Configuracion final con el usuario
read -p "Habilitar uso para DMZ [y/N]: " enable_dmz
if [ "$enable_dmz" = "y" ]; then
if [ -n "$if_dmz" ]; then
#call metodo_valida_interfaz
echo "invocamos al metodo de validacion de interfaz"
else
echo " Interfaces Disponibles:"
#Imprimimos el listado de interfaces
ifconfig -a | awk 'BEGIN{FS="[ ]+" ; RS=""} $1!~/lo/{print " " NR ") " $1}'
read -p " Nombre de la interfaz a usar: " if_dmz

#call metodo_valida_interfaz
#echo "invocamos al metodo de validacion de interfaz"

echo -n " >>IP: " ;
#Se imprime la direccion IP de la interfaz $if_dmz
ifconfig $if_dmz | grep 'inet:' | awk 'BEGIN{FS="[ ]+"} {print $3}' | awk 'BEGIN{FS=":"}{print $2}'
read -p " Desea conservar esta IP para esta interfaz [y/N]: " tmp_ans
if [ "$tmp_ans" != "y" ]; then
read -p " Nueva IP: " ip_dmz
ifconfig $if_dmz $ip_dmz
fi
fi
fi

read -p "Habilitar el modo paranoico [y/N]: " enable_paranoico_mode


echo "Aplicando reglas del firewall..."


#Borrado de las reglas aplicadas actualmente (flush)
iptables -F #flush todas las cadenas
iptables -t nat -F
iptables -X #Borra cadenas definidas por el usuario
iptables -Z

#Activamos bitacora de reenvio
iptables -t nat -A PREROUTING -j LOG
iptables -t nat -A POSTROUTING -j LOG

#Politicas por defecto (INPUT OUTPUT FORWARD)
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
iptables -t nat -P PREROUTING ACCEPT
iptables -t nat -P POSTROUTING ACCEPT

#REDIRECCIONAMIENTO A SERVIDOR WEB EN DMZ DESDE LA LAN Y RED PUBLICA
iptables -t nat -A PREROUTING -i $if_lan -s $id_lan -d $ip_lan -p tcp --dport 80 -j DNAT --to 192.168.1.1:80
iptables -t nat -A PREROUTING -i $if_pub -d $ip_pub -p tcp --dport 80 -j DNAT --to 192.168.1.1:80
#iptables -t nat -A PREROUTING -i $if_lan -s 0.0.0.0 -d 255.255.255.255 -p udp --dport 67 -j DNAT --to 192.168.1.129:67

#ABRIENDO PUERTOS PARA INPUT, OUTPUT, FORWARD: TRABAJO SUCIO PERO HAY QUE HACERLO!

#Aceptamos peticiones de ICMP para la LAN.
iptables -A INPUT -i $if_lan -s $id_lan -d $ip_lan -p icmp -j ACCEPT
iptables -A OUTPUT -o $if_lan -s $ip_lan -d $id_lan -p icmp -j ACCEPT

if [ "$enable_dmz" = "y" ]; then
#Aceptamos peticiones e ICMP para la DMZ.
iptables -A INPUT -i $if_dmz -s $id_dmz -d $ip_dmz -p icmp -j ACCEPT
iptables -A OUTPUT -o $if_dmz -s $ip_dmz -d $id_dmz -p icmp -j ACCEPT
fi

#Aceptamos peticiones ICMP desde la red publica.
iptables -A INPUT -i $if_pub -s 0/0 -p icmp --icmp-type 8 -j ACCEPT
iptables -A OUTPUT -o $if_pub -d 0/0 -p icmp --icmp-type 0 -j ACCEPT

#Aceptamos el flujo para el DNS para la LAN. REVISAR
iptables -A INPUT -i $if_lan -p udp --dport 67 -j ACCEPT
iptables -A OUTPUT -o $if_lan -p udp --sport 67 -j ACCEPT

if [ "$enable_paranoico_mode" != "y" ]; then
#Aceptamos navegar en la web. (Opcional)
iptables -A INPUT -i $if_pub -p tcp --sport 80 -j ACCEPT
iptables -A OUTPUT -o $if_pub -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -i $if_pub -p tcp --sport 443 -j ACCEPT
iptables -A OUTPUT -o $if_pub -p tcp --dport 443 -j ACCEPT

#Aceptamos las peticiones de MSNP, tenemos tolerancia. xD (Opcional)
iptables -A INPUT -i $if_pub -p tcp --sport 1863 -j ACCEPT
iptables -A OUTPUT -o $if_pub -p tcp --dport 1863 -j ACCEPT
fi

#Aceptamos el flujo de DNS para la red publica. REVISAR
iptables -A INPUT -i $if_pub -p udp --sport 53 -j ACCEPT
iptables -A OUTPUT -o $if_pub -p udp --dport 53 -j ACCEPT

if [ "$enable_dmz" = "y" ]; then
#Permitimos el flujo de de comununicacion entre el WEB server de la DMZ y los clientes de la LAN
#Evitamos rafagas de paquetes syn.
iptables -A FORWARD -i $if_lan -o $if_dmz -s $id_lan -d $web_server -p tcp --dport 80 -m limit --limit 3/minute --limit-burst 3 state --state NEW,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $if_dmz -o $if_lan -s $web_server -d $id_lan -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT

#Permitimos el flujo de de comununicacion entre el DNS server de la DMZ y los clientes de la LAN
iptables -A FORWARD -i $if_lan -o $if_dmz -s $id_lan -d $dns_server -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -i $if_dmz -o $if_lan -s $dns_server -d $id_lan -p udp --sport 53 -j ACCEPT

#Permitimos el flujo de de comununicacion entre el MAIL server de la DMZ y los clientes de la LAN
iptables -A FORWARD -i $if_lan -o $if_dmz -s $id_lan -d $mail_server -p tcp --dport 25 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $if_dmz -o $if_lan -s $mail_server -d $id_lan -p tcp --sport 25 -m state --state ESTABLISHED -j ACCEPT

#Permitimos el flujo de de comununicacion entre el MAIL server de la DMZ y los clientes de la LAN
iptables -A FORWARD -i $if_lan -o $if_dmz -s $id_lan -d $mail_server -p tcp --dport 110 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $if_dmz -o $if_lan -s $mail_server -d $id_lan -p tcp --sport 110 -m state --state ESTABLISHED -j ACCEPT

#Permitimos el flujo de de comununicacion entre el MAIL server de la DMZ y los clientes de la LAN
iptables -A FORWARD -i $if_lan -o $if_dmz -s $id_lan -d $mail_server -p tcp --dport 143 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $if_dmz -o $if_lan -s $mail_server -d $id_lan -p tcp --sport 143 -m state --state ESTABLISHED -j ACCEPT

#Permitimos el flujo de ICMP hacia el servidor web
iptables -A FORWARD -i $if_lan -o $if_dmz -s $id_lan -d $web_server -p icmp -j ACCEPT
iptables -A FORWARD -i $if_dmz -o $if_lan -s $web_server -d $id_lan -p icmp -j ACCEPT

#Permitimos a nuestro servidor DNS, solicitar direcciones al DNS del ITMorelia
iptables -A FORWARD -i $if_dmz -o $if_pub -s $dns_server -d 200.33.171.1 -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -i $if_pub -o $if_dmz -s 200.33.171.1 -d $dns_server -p udp --sport 53 -j ACCEPT

#iptables -A FORWARD -i $if_dmz -o $if_pub -p udp --dport 53 -j ACCEPT
#iptables -A FORWARD -i $if_pub -o $if_dmz -p udp --sport 53 -j ACCEPT

#Permitimos a nuestro servidor DNS, solicitar direcciones al DNS del ITMorelia
iptables -A FORWARD -i $if_dmz -o $if_pub -s $dns_server -d 200.33.171.8 -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -i $if_pub -o $if_dmz -s 200.33.171.8 -d $dns_server -p udp --sport 53 -j ACCEPT

#Permitimos exponer nuestro webserver a la red publica.
iptables -A FORWARD -i $if_pub -o $if_dmz -d $web_server -p tcp --dport 80 -m limit --limit 5/minute --limit-burst 5 -j ACCEPT
iptables -A FORWARD -i $if_dmz -o $if_pub -s $web_server -p tcp --sport 80 -j ACCEPT
else
#Sino hay DMZ permitimos a los clientes LAN consultar DNS externos
iptables -A FORWARD -i $if_lan -o $if_pub -s $id_lan -p udp --dport 53 -j ACCEPT
iptables -A FORWARD -i $if_pub -o $if_lan -d $id_lan -p udp --sport 53 -j ACCEPT
fi

#Permitimos a las personas de la LAN, navegar en la web.
iptables -A FORWARD -i $if_lan -o $if_pub -s $id_lan -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $if_pub -o $if_lan -d $id_lan -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
iptables -A FORWARD -i $if_lan -o $if_pub -s 172.16.1.21 -p tcp --dport 443 -j ACCEPT ##1863 :1503 3389
iptables -A FORWARD -i $if_pub -o $if_lan -d 172.16.1.21 -p tcp --sport 443 -j ACCEPT

#Permitimos el uso del MSNP en la computadora del SysAdmin dentro de la LAN
iptables -A FORWARD -i $if_lan -o $if_pub -s 172.16.1.21 -p tcp --dport 1863 -j ACCEPT ##1863 :1503 3389
iptables -A FORWARD -i $if_pub -o $if_lan -d 172.16.1.21 -p tcp --sport 1863 -j ACCEPT
iptables -A FORWARD -i $if_lan -o $if_pub -s 172.16.1.21 -p udp --dport 1863 -j ACCEPT
iptables -A FORWARD -i $if_pub -o $if_lan -d 172.16.1.21 -p udp --sport 1863 -j ACCEPT

#ENMASCARAMIENTO DE LA RED Y LA DMZ
iptables -t nat -A POSTROUTING -o $if_pub -s $id_lan -j MASQUERADE
if [ "$enable_dmz" = "y" ]; then
iptables -t nat -A POSTROUTING -o $if_pub -s $dns_server -p udp --dport 53 -j MASQUERADE
iptables -t nat -A POSTROUTING -o $if_pub -s $id_dmz -j MASQUERADE
iptables -t nat -A POSTROUTING -o $if_dmz -s $id_lan -d $web_server -p tcp --dport 80 -j SNAT --to-source $ip_dmz
iptables -t nat -A POSTROUTING -o $if_dmz -s ! $id_lan -d $web_server -p tcp --dport 80 -j SNAT --to-source $ip_dmz
#iptables -t nat -A POSTROUTING -o $if_dmz -s 0.0.0.0 -d $dhcp_server -p udp --dport 67 -j SNAT --to-source $ip_dmz
fi

echo "Reglas aplicadas correctamente :)"