Configurando el firewall con iptables

Una de las cosas que más me preocupan en la informática es la seguridad aunque en realidad no tengo ni puñetera idea (con perdón por la expresión). Así que llegó el momento de configurar el corta fuegos, en inglés firewall, del servidor donde se aloja este blog, para que nadie, insisto nadie, pudiera conectarse al blog por el puerto de Ghost por defecto sino solo por el 80 tal y como está ahora (en el futuro también el 443; pero esto es otro post ya que está pendiente de hacer). Puedes probar que no miento, añadiendo :2368 en el dominio y lo que quieras… A tu rollo, eso sí, si consigues petarlo avisame para ver que tengo que cambiar y ayudarme por favor.
La seguridad es muy importante.

Políticas por defecto

Digamos que hablamos de personas paranoicas, y si algo nos ha demostrado Snowden es que debemos de serlo si queremos estar seguros. Pues bien con esto de los firewall tenemos dos opciones, la primera es decir a todo que no de primeras y ya luego, si eso, pues te acepto lo que siga determinadas reglas. Lo que sería algo así como empezar el iptables con:

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

Y luego está el otro plan, el que aceptamos todo por defecto, agregamos nuestras reglas y luego rechazamos:

iptables -P FORWARD ACCEPT  
iptables -P INPUT   ACCEPT  
iptables -P OUTPUT  ACCEPT

## Nuestras reglas por aquí

#Rechazamos
iptables -A INPUT DROP  
iptables -A OUTPUT DROP  
iptables -A FORWARD DROP  

Por lo visto según este artículo, es mejor REJECT que DROP, pero cuando yo apliqué este método a pesar de que con nmap me chivaba que solo tenía dos puertos abiertos (era lo que buscaba) me aparecían en la configuración como parte de las reglas ICMP y no me dio mucha confianza así que volví al primer método de denegar todo.

Guardando reglas que es gerundio

Una de las putadas es que las reglas no tienen persistencia, es decir se borran por lo que estaría muy bien lo de guardarlas en un archivo.
Pues para esto se incluyen un par de comandos muy útiles, iptables-save e iptables-restore y su uso es muy sencillo:

  • iptables-save nos devuelve todas las reglas como si de un cat a un archivo se tratara por lo que solo tenemos que meter eso en un archivo:
$ iptables-save > myfirewall.rules
  • iptables-restore pues esta claro para que sirve, ¿no? Solo como apunte, hay un modificador -n o --noflush que permite que al restaurar las reglas no elimine las existentes. En tu mano queda saber cuando te puede interesar usarlo. Para restaurar las reglas usamos:
$ iptables-restore < myfirewall.rules

También existe un parámetro --test o -t para verificar que no va a fallar al cargar el archivo, te recomiendo usarlo antes de restaurar el archivo.

Persistencia de reglas

Lo de perder las reglas al reinciar me provocaba una inseguridad total y un malestar tremendo en mi organismo, ya que necesitamos que si el servidor se reinicia “accidentalmente” o porque alguien consigue forzarlo a que lo haga, o yo mismamente lo reincio porque me equivoco al añadir una regla y no es accesible por ssh, siga manteniendo las mismas reglas de seguridad (las que dejes guardadas no todas las que aplicas directamente). Así que para ello existe un paquete en distribuciones Debian/Ubuntu que se llama iptables-persistent, para instalarlo es sencillo, tan solo debemos sudar un poco:

# sudo apt-get install iptables-persistent

Con este paquete nos cargará automaticamente las reglas guardadas en /etc/iptables/rules.v4 y lo mismo pero acabado en 6 en vez de 4. Por lo que después para guardar nuestras reglas tan solo debemos de sustituir ese archivo usando iptables-save. Por lo que puedes probar y si te funciona, guardas y listo (si no siempre te quedará Paris o reinciar usando el KVM si es un servidor contratado o el botonazo y rezar aunque no creas si lo tienes en casa ?).

Docker

Al iniciar el demonio de Docker este crea unas reglas en el firewall iptables del kernel de linux para poder funcionar, entre otras cosas, permite, por ejemplo, hacer los links entre contenedores. Puedes ver más información al respecto en la web de Docker para el asunto. Yo os incluyo las reglas (en el siguiente punto) que creó “mi Docker” pero sabed que si no os funcionan o “las perdieseis” basta con que reiniciéis el servidor de docker:

$ service docker restart

Si eso no bastara, pararlo (stop) e iniciarlo (start).

Os puede pasar que no os enlacen los contenedores (links) debido a que si guardáis usando iptables-persistent las reglas se cargan después de que se inicie docker (¿puede ser esto un vector de ataque? Si lo sabes escríbeme para citar algún artículo al respecto o escribir uno por favor) y esto ocasiona que al no tener la cadena (chain) DOCKER en el iptables no agregue nuevas reglas.

Capar a cierta ip o rango de ip’s

Puede que sufras varios ataques a lo largo del tiempo y no te interese que ciertas ips accedan a ningún servicio de tú servidor, para ello puedes usar:

$ iptables -A INPUT -s X.X.X.X -j DROP
IPv6

Linux incorpora en su Kernel iptables tanto para IPv4 como IPv6, para ello en vez de usar el comando iptables de IPv4 tendrás que usar ip6tables para IPv6. Recomiendo poner todas las mismas reglas o denegar por defecto IPv6. Los usuarios domésticos (que yo sepa) aún no se van a conectar por IPv6 aunque lo soporten ya sus routers porque no está migrada gran parte de la red.

Si bien muchos proveedores ya dan direcciones IPv6 para los servidores por lo que deberían ser navegables usando esta nueva versión del protocolo IP.

El Firewall

Pues sabiendo todo lo anterior, os dejo las reglas que yo he aplicado, tenéis que cargarlas usando iptables-restore. Recuerdo que os dejo las reglas de Docker por si acaso y que estas reglas permiten trafico por ssh (puerto 22), * http* (puerto 80) e ICMP (limitado) ÚNICAMENTE.

# Generated by iptables-save v1.6.0 on Sun Aug 21 01:33:53 2016
*filter
:INPUT DROP [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [93840:9920746]
:DOCKER - [0:0]
:LOGGING - [0:0]
-A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m state --state NEW -j DROP
-A INPUT -f -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG FIN,SYN,RST,PSH,ACK,URG -j DROP
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,PSH,ACK,URG NONE -j DROP
-A INPUT -i lo -j ACCEPT
-A INPUT -p tcp -m tcp --tcp-flags ACK ACK -j ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 0 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 3 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 4 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 11 -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type 12 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 22 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
-A INPUT -j LOGGING
-A INPUT -p icmp -m limit --limit 1/sec --limit-burst 1 -j ACCEPT
-A INPUT -p icmp -m limit --limit 1/sec --limit-burst 1 -j LOG --log-prefix "PING-DROP:"
-A INPUT -p icmp -j REJECT --reject-with icmp-port-unreachable
-A FORWARD -i lo -o eth0 -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -i eth0 -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o eth0 -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -o lo -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 22 -m conntrack --ctstate ESTABLISHED -j ACCEPT
-A OUTPUT -p tcp -m tcp --sport 80 -m conntrack --ctstate ESTABLISHED -j ACCEPT
-A OUTPUT -p icmp -j ACCEPT
-A LOGGING -m limit --limit 2/min -j LOG --log-prefix "IPTables Packet Rejected: " --log-level 7
-A LOGGING -j REJECT --reject-with icmp-port-unreachable
COMMIT  
# Completed on Sun Aug 21 01:33:53 2016
# Generated by iptables-save v1.6.0 on Sun Aug 21 01:33:53 2016
*nat
:PREROUTING ACCEPT [21231:1271806]
:INPUT ACCEPT [15478:928608]
:OUTPUT ACCEPT [31187:1871284]
:POSTROUTING ACCEPT [31187:1871284]
:DOCKER - [0:0]
COMMIT  
# Completed on Sun Aug 21 01:33:53 2016

NOTA: Normalmente los proveedores de servicios vps o dedicado ofrecen monitorización de los mismos por lo que tendrás que habilitar el trafico que viene de sus servidores de monitorización.