Esta vez vamos hacer un post tirando más a bloc de notas (el segundo después del de los certificados, igual ya es la edad), ya que si hemos trabajado con iptables, las reglas que vamos a comentar están al orden del día.
Las explicaciones están basadas en una debian, la idea principal es añadir algunas reglas por defecto que nos permitan proteger nuestro sistemas ante algunos tipos de ataques, por ejemplo DDOS o Pings de la muerte!, no son la panacea, pero algo hacen.
Lo primero que voy hacer es intentar protegerme, para que en el caso que se nos vaya la mano (algo que suele pasar) con alguna regla, pues no nos quedemos sin acceso a la máquina, así en mi caso como estoy conectado por ssh, lo que voy hacer es controlar que mi usuario este conectado y en el caso que se desconecte, pues borramos todas las reglas y santas pascuas. Seria algo tan sencillo como
#!/bin/bash USUARIO=Nombre who | grep ${USUARIO} if [ $? -ne 0 ]; then echo "Stopping firewall and allowing everyone..." iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -t mangle -F iptables -t mangle -X iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT exit 1 fi
Y lo podemos ejecutar cuando empecemos, por ejemplo con un while, tal que así.
while true ;do /bin/bash script.sh && sleep 10; done
Bueno pues ahora vamos a mirar las reglas que podemos ir poniendo y las vamos a ir explicando, así si se entiende pues cada cual puede utilizarlas como mejor le vaya.
Vamos a utilizar muy mucho -m recent, básicamente los que nos permite hacer es crear un fichero temporal donde vamos almacenar las ips que cumplan los patrones del ataque, de esta manera podremos comprobar el numero de veces que una ip esta intentando acceder a nuestro sistema. También vamos hacer uso del -N, pongamos, por ejemplo que queremos logar (que va a ser el caso) aquellas peticiones que cumplan nuestras reglas, en este caso tendremos que realizar dos reglas, la primera para logar y la segunda para hacer el DROP. Por ejemplo,
iptables -A INPUT -s 10.0.0.0/8 -j LOG --log-level 4 -log-prefix 'SourceDrop ' iptables -A INPUT -s 10.0.0.0/8 -j DROP
Esto si tenemos unas cuantas reglas en un rollo bastante grande, así que para mejorar lo que haremos es utilizar chains, como funcionan? pues muy fácil, creamos un chail tal que así
iptables -N LOGandDROP
Con la opcion -A lo que vamos hacer es añadir las reglas que queremos que tenga el chail.
iptables -A LOGandDROP -j LOG --log-level 6 --log-prefix 'IPDROP ' iptables -A LOGandDROP -j DROP
Y ahora si queremos volver a crear la regla de antes lo que haremos es
iptables -A INPUT -s 10.0.0.0/8 -j LOGandDROP
Nos ahorramos como el 50% de las reglas…. en este caso. Vamos al lío.
Control de los accesos al puerto 22, uno de los puertos que solemos tener abiertos es el 22 así que vamos a montar unas reglas para que en el caso que detectemos muchos accesos en un periodo de tiempo, pues los bloqueemos, esta va a ser bien bien la base de la mayoría de reglas. Vamos hacer un chain que se llame SSH, para ser originales
iptables -N SSH iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j SSH iptables -A SSH -m recent --set --name SSH --rsource iptables -A SSH -m recent --update --seconds 30 --hitcount 5 --name SSH --rsource -j LOG --log-prefix "Firewall SSH-Bruteforce: " --log-level 6 iptables -A SSH -m recent --update --seconds 30 --hitcount 5 --name SSH --rsource -j DROP
Donde
–name es el nombre de la «clase» que defines ,
–rsource que se mantenga en la lista utilizando la ip remota
–rcheck mirar si la ip esta en la lista
—update si esta en la lista hace una actualización del timestamp
–seconds numero de segundos para rastrear la dirección
—hitcount numero de peticiones que aceptamos en el numero de segundo que definimos.
En este ejemplo que tenemos? muy fácil tenemos primero la regla de INPUT donde le decimos que si se cumple lo que tiene que haces es ir al chai SSH, o sea que si la petición vienen al 22 aplicara las reglas de chai SSH, y que hacen estas reglas? Pues si la ip que hace la petición al puerto 22 no hizo mas de 5 hits en el tiempo en segundo que hemos dicho hará el accept, en caso contrario pues DROP que te crió!.
Esto lo podemos hacer para todos los puertos que nos interese o para rangos, grupos etc Ahora vamos a mirar de protegernos del scanner de puertos.
Aplicaremos las siguientes reglas y las explicamos.
Paquetes mal formados o vacíos
En la primera lo que estamos haciendo es decirle que todas las peticiones entrantes sin –tcp-flags(SYN, ACK, FIN, RST, URG, PSH) que haga más de 3 por minuto y con un pico máximo de 5 se envíen al log
iptables -A INPUT -p tcp --tcp-flags ALL NONE -m limit --limit 3/m --limit-burst 5 -j LOG --log-prefix "Firewall Scan Ports "
En la siguiente lo que hacemos es decirle que aquellas ip que estén en la blacklist que se bloqueen durante 60 segundos.
iptables -A INPUT -p tcp --tcp-flags ALL NONE -m recent --name blacklist_60 --set -m comment --comment "Drop/Blacklist ip Scan Ports" -j DROP
Mas cosas.
TCP-reset
Lo que sale en el gif que me encontré que lo explica muy bien. http://i29.tinypic.com/103ybo8.jpg
iptables -N tcp-reset iptables -A tcp-reset -m limit --limit 3/second --limit-burst 8 -j LOG --log-prefix "Firewall tcp-reset " --log-level 6 iptables -A tcp-reset -p tcp -j REJECT --reject-with tcp-reset iptables -A tcp-reset -j REJECT
ICMP- control
iptables -N ICMP iptables -A ICMP -p icmp -m limit --limit 1/s --limit-burst 2 -j LOG --log-prefix "Firewall PING-DROP" --log-level 6 iptables -A ICMP -p icmp -m limit --limit 1/s --limit-burst 2 -j DROP
syn-flood –> Denial-of -service
iptables -N syn-flood iptables -A syn-flood -m limit --limit 50/second --limit-burst 100 -j LOG --log-prefix "Firewall syn-flood " iptables -A syn-flood -j DROP
Paquetes mal formados.
iptables -N PKT_FAKE iptables -A PKT_FAKE -m state --state INVALID -j DROP iptables -A PKT_FAKE -p tcp --dport 80 --tcp-flags ALL ACK,RST,SYN,FIN -j LOG --log-prefix "Firewall PKT_FAKE " iptables -A PKT_FAKE -p tcp --dport 80 --tcp-flags SYN,FIN SYN,FIN -j LOG --log-prefix "Firewall PKT_FAKE " iptables -A PKT_FAKE -p tcp --dport 80 --tcp-flags SYN,RST SYN,RST -j LOG --log-prefix "Firewall PKT_FAKE " iptables -A PKT_FAKE -p tcp --dport 80 ! --syn -m state --state NEW -j LOG --log-prefix "Firewall PKT_FAKE " iptables -A PKT_FAKE -f -j LOG --log-prefix "Firewall PKT_FAKE " iptables -A PKT_FAKE -j RETURN
Drop lista de ips IANA
iptables -A INPUT -s 0.0.0.0/7 -j DROP iptables -A INPUT -s 2.0.0.0/8 -j DROP iptables -A INPUT -s 5.0.0.0/8 -j DROP iptables -A INPUT -s 7.0.0.0/8 -j DROP iptables -A INPUT -s 10.0.0.0/8 -j DROP iptables -A INPUT -s 23.0.0.0/8 -j DROP iptables -A INPUT -s 27.0.0.0/8 -j DROP iptables -A INPUT -s 31.0.0.0/8 -j DROP iptables -A INPUT -s 36.0.0.0/7 -j DROP iptables -A INPUT -s 39.0.0.0/8 -j DROP iptables -A INPUT -s 42.0.0.0/8 -j DROP iptables -A INPUT -s 49.0.0.0/8 -j DROP iptables -A INPUT -s 50.0.0.0/8 -j DROP iptables -A INPUT -s 77.0.0.0/8 -j DROP iptables -A INPUT -s 78.0.0.0/7 -j DROP iptables -A INPUT -s 92.0.0.0/6 -j DROP iptables -A INPUT -s 96.0.0.0/4 -j DROP iptables -A INPUT -s 112.0.0.0/5 -j DROP iptables -A INPUT -s 120.0.0.0/8 -j DROP iptables -A INPUT -s 169.254.0.0/16 -j DROP iptables -A INPUT -s 172.16.0.0/12 -j DROP iptables -A INPUT -s 173.0.0.0/8 -j DROP iptables -A INPUT -s 174.0.0.0/7 -j DROP iptables -A INPUT -s 176.0.0.0/5 -j DROP iptables -A INPUT -s 184.0.0.0/6 -j DROP iptables -A INPUT -s 192.0.2.0/24 -j DROP iptables -A INPUT -s 197.0.0.0/8 -j DROP iptables -A INPUT -s 198.18.0.0/15 -j DROP iptables -A INPUT -s 223.0.0.0/8 -j DROP iptables -A INPUT -s 224.0.0.0/3 -j DROP
Como le hemos dicho que nos envie los problemas al log lo que deberemos hacer es montar que iptables envie el log a un fichero, como? pues por el rsyslog, asi que vamos al lio.
Vamos a crear las carpetas donde vamos a dejar los logs, en mi caso los tengo en mnt así que haremos
mkdir -p /mnt/log/firewall touch /mnt/log/firewall/iptables.log chmod 600 /mnt/log/firewall/iptables.log chown root:adm //mnt/log/firewall/iptables.log
Lo normal es que se envien los logs a rsyslog y sea este el que debamos configurar para que escriba en el log, la configuracion del rsyslog la coge por defecto del directorio /etc/rsyslog.d/, ahí debermeos crear el fichero de configuracion para el firewall, tal que asi.
vi /etc/rsyslog.d/firewall.conf
:msg, startswith, "Firewall " -/mnt/usb/firewall/iptables.log & ~
Vale ahora vamos a configurar el logrotate, para que vaya limpiando el log y no se nos haga infumable. creamos el fichero de configuracion en
vim /etc/logrotate.d/iptables.log
/mnt/usb/firewall/iptables.log { rotate 5 daily size 10M dateext missingok create 600 root adm notifempty compress delaycompress postrotate invoke-rc.d rsyslog reload > /dev/null endscript }
Reinicimos el servicio
/etc/init.d/rsyslog restart
Ahora podemos comprobar que funciona, haciendo una peticion nc al puerto 22. Y parasa esto.
while true; do nc -vz -w3 IP 22 && sleep 2 ; done Connection to ---------- 22 port [tcp/ssh] succeeded! Connection to ---------- 22 port [tcp/ssh] succeeded! Connection to ---------- 22 port [tcp/ssh] succeeded! Connection to ---------- 22 port [tcp/ssh] succeeded! nc: connect to ---------- port 22 (tcp) timed out: Operation now in progress nc: connect to ---------- port 22 (tcp) timed out: Operation now in progress nc: connect to ---------- port 22 (tcp) timed out: Operation now in progress nc: connect to ---------- port 22 (tcp) timed out: Operation now in progress
Al cabo de 30 segundos sin recivir peticiones liberaremos la ip.
Resumen lista de reglas
iptables -N LOGandDROP iptables -A LOGandDROP -j LOG --log-level 6 --log-prefix 'IPDROP ' iptables -A LOGandDROP -j DROP iptables -N SSH iptables -A INPUT -p tcp -m tcp --dport 22 -m state --state NEW -j SSH iptables -A SSH -m recent --set --name SSH --rsource iptables -A SSH -m recent --update --seconds 30 --hitcount 5 --name SSH --rsource -j LOG --log-prefix "Firewall SSH-Bruteforce: " --log-level 6 iptables -A SSH -m recent --update --seconds 30 --hitcount 5 --name SSH --rsource -j DROP iptables -N HTTP iptables -A INPUT -p tcp -m tcp --dport 80 -m state --state NEW -j HTTP iptables -A HTTP -m recent --set --name HTTP --rsource iptables -A HTTP -m recent --update --seconds 30 --hitcount 30 --name HTTP --rsource -j LOG --log-prefix "Firewall HTTP-Bruteforce: " --log-level 6 iptables -A HTTP -m recent --update --seconds 30 --hitcount 30 --name HTTP --rsource -j DROP iptables -N HTTPS iptables -A INPUT -p tcp -m tcp --dport 443 -m state --state NEW -j HTTPS iptables -A HTTPS -m recent --set --name HTTPS --rsource iptables -A HTTPS -m recent --update --seconds 30 --hitcount 30 --name HTTPS --rsource -j LOG --log-prefix "Firewall HTTPS-Bruteforce: " --log-level 6 iptables -A HTTPS -m recent --update --seconds 30 --hitcount 30 --name HTTPS --rsource -j DROP iptables -N ICMP iptables -A ICMP -p icmp -m limit --limit 1/s --limit-burst 2 -j LOG --log-prefix "Firewall PING-DROP" --log-level 6 iptables -A ICMP -p icmp -m limit --limit 1/s --limit-burst 2 -j DROP iptables -A INPUT -p tcp --tcp-flags ALL NONE -m limit --limit 3/m --limit-burst 5 -j LOG --log-prefix "Firewall Scan Ports " iptables -A INPUT -p tcp --tcp-flags ALL NONE -m recent --name blacklist_60 --set -m comment --comment "Drop/Blacklist ip Scan Ports" -j DROP iptables -N syn-flood iptables -A syn-flood -m limit --limit 50/second --limit-burst 100 -j LOG--log-prefix "Firewall syn-flood " iptables -A syn-flood -j DROP iptables -N PKT_FAKE iptables -A PKT_FAKE -m state --state INVALID -j DROP iptables -A PKT_FAKE -p tcp --dport 80 --tcp-flags ALL ACK,RST,SYN,FIN -j LOG --log-prefix "Firewall PKT_FAKE_80 " iptables -A PKT_FAKE -p tcp --dport 80 --tcp-flags SYN,FIN SYN,FIN -j LOG --log-prefix "Firewall PKT_FAKE_80 " iptables -A PKT_FAKE -p tcp --dport 80 --tcp-flags SYN,RST SYN,RST -j LOG --log-prefix "Firewall PKT_FAKE_80 " iptables -A PKT_FAKE -p tcp --dport 80 ! --syn -m state --state NEW -j LOG --log-prefix "Firewall PKT_FAKE_80 " iptables -A PKT_FAKE -p tcp --dport 443 --tcp-flags ALL ACK,RST,SYN,FIN -j LOG --log-prefix "Firewall PKT_FAKE_443 " iptables -A PKT_FAKE -p tcp --dport 443 --tcp-flags SYN,FIN SYN,FIN -j LOG --log-prefix "Firewall PKT_FAKE_443 " iptables -A PKT_FAKE -p tcp --dport 443 --tcp-flags SYN,RST SYN,RST -j LOG --log-prefix "Firewall PKT_FAKE_443 " iptables -A PKT_FAKE -p tcp --dport 443 ! --syn -m state --state NEW -j LOG --log-prefix "Firewall PKT_FAKE_443 " iptables -A PKT_FAKE -f -j LOG --log-prefix "Firewall PKT_FAKE " iptables -A PKT_FAKE -j RETURN iptables -N tcp-reset iptables -A tcp-reset -m limit --limit 3/second --limit-burst 8 -j LOG --log-prefix "Firewall tcp-reset " --log-level 6 iptables -A tcp-reset -p tcp -j REJECT --reject-with tcp-reset iptables -A tcp-reset -j REJECT iptables -A INPUT -s 0.0.0.0/7 -j DROP iptables -A INPUT -s 2.0.0.0/8 -j DROP iptables -A INPUT -s 5.0.0.0/8 -j DROP iptables -A INPUT -s 7.0.0.0/8 -j DROP iptables -A INPUT -s 10.0.0.0/8 -j DROP iptables -A INPUT -s 23.0.0.0/8 -j DROP iptables -A INPUT -s 27.0.0.0/8 -j DROP iptables -A INPUT -s 31.0.0.0/8 -j DROP iptables -A INPUT -s 36.0.0.0/7 -j DROP iptables -A INPUT -s 39.0.0.0/8 -j DROP iptables -A INPUT -s 42.0.0.0/8 -j DROP iptables -A INPUT -s 49.0.0.0/8 -j DROP iptables -A INPUT -s 50.0.0.0/8 -j DROP iptables -A INPUT -s 77.0.0.0/8 -j DROP iptables -A INPUT -s 78.0.0.0/7 -j DROP iptables -A INPUT -s 92.0.0.0/6 -j DROP iptables -A INPUT -s 96.0.0.0/4 -j DROP iptables -A INPUT -s 112.0.0.0/5 -j DROP iptables -A INPUT -s 120.0.0.0/8 -j DROP iptables -A INPUT -s 169.254.0.0/16 -j DROP iptables -A INPUT -s 172.16.0.0/12 -j DROP iptables -A INPUT -s 173.0.0.0/8 -j DROP iptables -A INPUT -s 174.0.0.0/7 -j DROP iptables -A INPUT -s 176.0.0.0/5 -j DROP iptables -A INPUT -s 184.0.0.0/6 -j DROP iptables -A INPUT -s 192.0.2.0/24 -j DROP iptables -A INPUT -s 197.0.0.0/8 -j DROP iptables -A INPUT -s 198.18.0.0/15 -j DROP iptables -A INPUT -s 223.0.0.0/8 -j DROP iptables -A INPUT -s 224.0.0.0/3 -j DROP
Ahora para que siempre este disponible al reiniciar la maquina haremos.
#!/bin/bash iptables-save > /etc/firewall.conf echo "#!/bin/sh" > /etc/network/if-up.d/iptables echo "iptables-restore < /etc/firewall.conf" >> /etc/network/if-up.d/iptables chmod +x /etc/network/if-up.d/iptables
Ale a difrturalo!
Hola
Estas reglas funcionan para FORWARD?
Gracias
No lo probé, pero debería ya que son reglas por conexión, independientemente el tipo.
Tengo una duda con esto de crear cadenas. Cuando creamos una cadena «- N «. a que tabla le aplicamos las restricciones… INPUT , OUTPUT o FORWARD?
saludos.
buen articulo
todo claro!! XD