Auto Defensa Digital
Auto Defensa Digital fue un taller sobre iptables
, ipset
y snort
que se hizo en el HackLab el 2015-02-07.
Contenido
Referencias
-
iptables
, en este formato nos estamos refiriendo al comando que se ejecuta en una línea de comandos (o shell, o terminal, o cli, como le quieran llamar)
Iptables
Iptables son las herramientas para administrar los filtros de paquetes del kernel linux. Con iptables se le puede indicar a linux qué hacer con cada paquete o conexión que recibe, ignorarla, rechazarla, reenviarla, etc. No solo es capaz de crear firewalls, sino también de convertir la computadora en un router.
En el taller vimos cómo crear un "statefull firewall", que es un firewall muy simple que hace análisis de cada conexión y sus estados, en lugar de cada paquete. La características principales de este firewall son:
- Se lo puede reiniciar sin perder las conexiones existentes
- Es simple, porque una vez que se permite una conexión, no es necesario volver a procesarla
Introducción a iptables
Iptables se maneja por reglas y acciones especificadas en la línea de comandos. Por defecto acepta todos los paquetes entrantes y salientes. Esto es un problema para la autodefensa digital, porque si tenemos un servicio que necesitamos que funcione localmente, pero no hacia afuera, y el kernel admite todas las conexiones, estamos aumentando nuestra superficie de ataque.
Con el comando iptables -nvL
vemos todas las reglas actuales (correrlo como root). Sin ninguna configuración se ve así:
Chain INPUT (policy ACCEPT 1919 packets, 452K bytes) pkts bytes target prot opt in out source destination Chain FORWARD (policy ACCEPT 5 packets, 300 bytes) pkts bytes target prot opt in out source destination Chain OUTPUT (policy ACCEPT 1666 packets, 415K bytes) pkts bytes target prot opt in out source destination
Cada cadena ("chain") indica la dirección de los paquetes, INPUT son los paquetes que llegan desde la red y OUTPUT los que salen. FORWARD solo tiene sentido si estamos configurando un router.
La política ("policy") de cada cadena indica la acción por defecto para cada paquete, si no hay ninguna especificada. En este caso, la política es ACCEPT, es decir aceptar cualquier paquete que entre o salga. Como decíamos esto es malo porque no tenemos control sobre las conexiones que se hacen hacia nuestra computadora y dependemos de la buena o mala configuración de los servicios.
Esta configuración no tiene ninguna regla, por lo que todo es aceptado y nada es analizado.
Las reglas de iptables
se analizan en orden de arriba para abajo, como una lista de condiciones que si se cumplen excluyen a las subsiguientes, pero que cuando no se cumplen, se continúa la comprobación.
Por eso es importante al leer otras guías que se pueden encontrar en Internet, que al correr los comandos desde una línea de comandos y nos olvidamos alguno, no lo pongamos después, porque el orden de las reglas (y los comandos que corrimos para agregarlas) es importante y pueden fallar cosas o no funcionar como esperábamos. Hay forma de insertar reglas en un orden determinado, pero es un poco más complejo, porque hay que saber entre cuáles reglas va la que queremos insertar.
De todas formas no es recomendable escribir las reglas de iptables a mano, porque cuando se reinicia la computadora se pierden y hay que volverlas a escribir. En Internet van a encontrar que hay muchos scripts, bastante complejos algunos, que se encargan de levantar las reglas cada vez. Esto ya no es necesario porque hace tiempo iptables
soporta iptables-save
e iptable-restore
para volcar las reglas actuales en un archivo y volverlas a recuperar.
Lo más simple es hacer un volcado original de las reglas sin modificar a un archivo y agregar las reglas propias ahí mismo. Con esto nos aseguramos que las reglas están escritas en el orden adecuado y que las vemos como un todo en lugar de reglas sueltas. Luego se pueden recuperar con el comando iptables-restore < reglas.rules
.
En esta guía se asume que las reglas están en el archivo /etc/iptables/iptables.rules
y que existe un servicio que se encarga de correr iptables-restore
cuando lo considere adecuado. Esto nos asegura que entre reinicios del firewall, mientras hacemos pruebas, las reglas de filtrado del kernel se vacían y se vuelven a completar únicamente con las reglas que le decimos. Esto evita incoherencias y dolores de cabeza. En Parabola (o Arch, o derivados), este servicio es systemctl restart iptables
.
Creando un firewall
El objetivo de crear un firewall es tener un mejor control sobre las conexiones que aceptamos. Este firewall ignora cualquier conexión por defecto y solo permite las que especificamos. En este caso solo hablamos de reglas en la cadena INPUT y porque no nos interesa filtrarnos a nosotras mismas, dejamos la cadena OUTPUT tal cual estaba.
El firewall completo se puede descargar acá. Acá tiene color. Cada regla tiene su comentario, explicando para qué sirve.
El archivo iptables.rules
se puede descargar dentro de /etc/iptables/
y activar con iptables-restore </etc/iptables/iptables.rules
. Para ejecutarlo al inicio del sistema, usar el servicio de la distribución GNU/Linux, o agregar el comando anterior al archivo /etc/rc.local
.
Si no existe ese archivo se lo tiene que crear bajo el nombre rc.local agregar como primer linea #!/bin/bash
y luego iptables-restore </etc/iptables/iptables.rules
. Para que funcione ese archivo deberá ser ejecutable, cosa que se puede hacer corriendo en la consola sudo chmod +x rc.local
TODO: Faltan reglas para detectar escaneos con nmap |
*filter # Políticas por defecto # # Ignorar todas las conexiones entrantes que no hayamos permitido # específicamente :INPUT DROP [0:0] # Esta computadora no es un router (aun) :FORWARD DROP [0:0] # Permitirnos todo :OUTPUT ACCEPT [0:0] # Comienzo del firewall # Bloquear garcas # # Esta regla solo tiene sentido con ipset, crear la tabla con `ipset # create garcas hash:net` y agregar direcciones IPv4 que queramos # bloquear en el firewall con `ipset add garcas 8.8.8.8` donde 8.8.8.8 # es la IPv4 a bloquear. # # -A INPUT -m set --match-set garcas src,dst -j REJECT --reject-with icmp-host-unreachable -m comment --comment "GARCAS" # Permitir las conexiones ya validadas # # Cuando una conexión no está establecida, es decir que es # potencialmente aceptable, esta regla falla y se siguen procesando las # reglas posteriores. Una vez que la conexión pasa alguna de las reglas # posteriores, se la considera establecida, por lo que es aceptada # automáticamente. # # La contra de esta regla genérica es que no se puede contar la cantidad # de datos transferidos por tipo de conexión. Pero tiene a favor que el # firewall es muy simple porque tiene un solo punto de ingreso. -A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -m comment --comment "VALIDOS" # Ignorar conexiones inválidas # # En algunos casos las conexiones vienen con paquetes inválidos, pero en # otras los escaner de red como nmap usan paquetes inválidos para hacer # detección de servicios. Esta regla los ignora. # # TODO: en realidad habría que rechazarlos de forma inteligente. -A INPUT -m conntrack --ctstate INVALID -j DROP -m comment --comment "INVALIDOS" # Pings # # Para saber que el host está levantado y andando, tiene que poder # responder pings. Sin esta regla los pings no se responden. También # se los puede rechazar, haciéndole creer a la otra punta (un nmap por # ejemplo) que nuestro host no está funcionando. Es como un manto de # invisibilidad. La contra es que nosotras tampoco vamos a poder saber # si nuestro host está funcionando, si no estamos en el mismo espacio # físico. # Aceptarlos -A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -j ACCEPT -m comment --comment "PINGS" # Rechazarlos # -A INPUT -p icmp -m icmp --icmp-type 8 -m conntrack --ctstate NEW -J REJECT --reject-with icmp-host-unreachable # Rechazar todas las conexiones nuevas que no sean NEW # # Sólo aceptamos conexiones no establecidas que sean nuevas. Si el host # remoto intenta conectarse con nosotras sin negociar una conexión # antes, le decimos que intente de vuelta. # # Son dos reglas distintas porque UDP y TCP manejan las conexiones de # forma distinta. -A INPUT -p udp -m conntrack ! --ctstate NEW -j REJECT --reject-with icmp-port-unreachable -A INPUT -p tcp -m tcp ! --tcp-flags FIN,SYN,RST,ACK SYN -m conntrack ! --ctstate NEW -j REJECT --reject-with tcp-reset # Aceptar localhost # # La interfaz lo(calhost) es confiable para nosotras y la aceptamos. -A INPUT -i lo -j ACCEPT # Abrir puertos # # A partir de acá empezamos a permitir conexiones dependiendo del puerto # destino. Por cada servicio que queramos exponer a hosts remotos, hay # que crear una regla aceptando su puerto y protocolo IP. # SSH # # Aceptamos SSH en el puerto 22 y en el 1863 -A INPUT -p tcp -m multiport --dports 1863,22 -j ACCEPT -m comment --comment "SSH" # HTTP # # Sólo tenemos servidores HTTP en los puertos 80 y 443. -A INPUT -p tcp -m multiport --dports 80,443 -j ACCEPT -m comment --comment "HTTP" # Mail # # Los servidores de correo utilizan varios puertos. La primera regla # acepta los puertos de SMTP y la segunda de POPS e IMAPS -A INPUT -p tcp -m multiport --dports 25,465,587 -j ACCEPT -m comment --comment "SMTP" -A INPUT -p tcp -m multiport --dports 995,993 -j ACCEPT -m comment --comment "MAIL" # XMPP # # Los servidores jabber funcionan en estos puertos -A INPUT -p tcp -m multiport --dports 5222,5269,5280,5298 -j ACCEPT -m comment --comment "XMPP" # mDNS # # Permitir tráfico de avahi-daemon -A INPUT -p udp --dport 5353 -d 224.0.0.251 -j ACCEPT # Servidor DNS # # Si tenemos un servidor DNS abierto necesita el puerto 53 en ambos # protocolos abierto. -A INPUT -p udp --dport 53 -j ACCEPT -A INPUT -p tcp --dport 53 -j ACCEPT # Fin del firewall COMMIT
Ipset
Falta escribir esto
Snort
Falta escribir esto