terminal-comandos

Este es un tutorial orientado sobre todo a los cubanos y a la gente de la UCI, que somos los que generalmente tenemos problemas con la cuota mensual de acceso a Internet. Quizás a muchos de ustedes les pasa como a mí, que la cuota de Internet prácticamente no me alcanza para el mes y he tenido hasta que repartirla en cuotas diarias.

El problema…

Este problema me ha llevado a aplicar cualquier cantidad de trucos para eliminar las cosas superfluas de la navegación, como por ejemplo, usar extensiones de Firefox para no cargar automáticamente las imágenes, videos, animaciones, etc. y bloquear determinados sitios. Algunas de estas extensiones son ImgLikeOpera o BlockSite Plus. Pero si nos detenemos a revisar nuestros logs del proxy — en el caso de la UCI están accesibles para cada usuario —  nos encontramos que hay sitios que son “imbloqueables” con estas extensiones, como son addons.mozilla.com, addons.mozilla.org, data.mozilla.com, … sitios a los que se conecta el navegador a hacer quien sabe qué cosas a través de funcionalidades que al parecer no están accesibles para que las extensiones del navegador las bloqueen.

Por otro lado, existe una proliferación de lo que se conoce como Content Delivery Network (CDN), conjunto de servidores de alta disponibilidad contratados por los distintos sitios a proveedores de servicio de Internet donde se almacenan los contenidos estáticos, de forma que empresas especializadas se encargan de manejar los altos volúmenes de tráfico que genera el servir esos archivos, muchos de gran tamaño, disminuyendo la carga sobre el sitio que los referencia. El problema es que muchas veces esos contenidos (imágenes, CSS, Javascript, …) no nos interesa, sólo queremos leer el texto. ¡Y mira que esos CDN gastan cuota! Lo bueno es que casi todos contienen las cadenas de caracteres “cnd.” o “-cdn” o “cdn-” en el dominio… ;-)

Configuración básica de iptables

El super cortafuegos de Linux viene al rescate. Olvídense de todas las interfaces bonitas como Uncomplicated Firewall (ufw) y demás herramientas de lamers. Porque ya saben: “real men use iptables!” :-D

En Debian/Ubuntu/Nova, desinstala todos esos paquetes que has instalado porque te da demasiado miedo usar un cortafuegos de verdad, e instálate el paquete iptables-persistent. Con este paquete tienes un script en /etc/init.d/iptables-persistent que te permite salvar y restaurar las reglas de iptables que hayas adicionado o insertado. También tienes los archivos /etc/iptables/rules.v4 y /etc/iptables/rules.v6 donde se salvan estas reglas para IPv4 e IPv6 respectivamente. Con los comandos iptables e ip6tables puedes adicionar, insertar o eliminar reglas del núcleo, las cuales puedes probar antes de salvarlas hacia los archivos anteriormente mencionados.

Si en tu entorno no se utiliza algunos de los protocolos IPv4 o IPv6 te recomiendo que dejes el archivo correspondiente con políticas básicas de denegar todo. Por ejemplo, acá en la UCI no se utiliza IPv6 (todavía) así que podemos hacer lo siguiente:

# ip6tables -F
# ip6tables -Z
# ip6tables -X
# ip6tables -P INPUT DROP
# ip6tables -P OUTPUT DROP
# ip6tables -P FORWARD DROP
# /etc/init.d/iptables-persistent save

Los tres primeros comandos son para limpiar la tabla de reglas, los otros tres son para establecer como política por defecto de IPv6 que nada entre ni salga por la red, y el último es para salvar las reglas en /etc/iptables/rules.v*, lo que garantiza que estas se carguen cada vez que se reinicie la máquina o cada vez que se corra /etc/init.d/iptables-persistent restart .
Claro, que es mucho más fácil sencillamente deshabilitar IPv6 en el sistema operativo, añadiendo una opción a los argumentos de tu núcleo. Esto lo logras editando /etc/default/grub, modificando la línea que contiene la variable GRUB_CMDLINE_LINUX_DEFAULT:

GRUB_CMDLINE_LINUX_DEFAULT="ipv6.disable=1 quiet splash"

Luego se actualiza grub y se reinicia:

# update-grub
# reboot

Después de deshabilitar IPv6 (y reiniciar) o denegarlo por completo, te puedes centrar en configurar IPv4. Primero, limpia la tabla de reglas y establece algunas políticas de seguridad por defecto:

# iptables -F
# iptables -Z
# iptables -X
# iptables -P INPUT DROP
# iptables -P FORWARD DROP
# iptables -P OUTPUT ACCEPT
# iptables -A INPUT -i lo -j ACCEPT
# iptables -A INPUT -p tcp -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A INPUT -p udp -m state --state RELATED,ESTABLISHED -j ACCEPT
# iptables -A INPUT -p icmp -m icmp ! --icmp-type 8 -j ACCEPT
# /etc/init.d/iptables-persistent save

Ya conocen los tres primeros comandos, en los tres siguientes sólo permitimos las conexiones salientes. Luego adicionamos excepciones que permitan algunas conexiones entrantes, en este caso a la interfaz de red loopback (127.0.0.0/8), también los paquetes de respuestas a conexiones preestablecidas, y cualquier paquete ICMP excepto las peticiones de ping… Ok, ok, si no eres tan paranoico puedes permitir todos los ping, quita de la regla que tiene que ver con ICMP la parte que dice ! --icmp-type 8 :-P :-)
Si además quieres abrir algún puerto que te interese que sea accesible desde el exterior, por ejemplo, para conexiones SSH (puerto 22), puedes añadir una regla como esta:

# iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT

Pon el número de puerto según te convenga: http(80), https(443), samba(445), …
Las reglas también se pueden escribir editando directamente el archivo /etc/iptables/rules.v4, recomiendo que salven alguna para que les sirva de plantilla.

Utilizando iptables para filtrar paquetes por contenido

Ok, vamos al pollo del arroz con pollo. :-)

Toda petición HTTP o HTTPS que se dirige al proxy, contiene un encabezado que incluye el dominio al que uno desea conectarse, por tanto, se podrían filtrar esos paquetes por las cadenas de caracteres que contienen y denegar los que no nos convegan. Por ejemplo, si no desean que vaya alguna petición para addons.mozilla.com o addons.mozilla.org, podemos añadir esta regla:

# iptables -A OUTPUT -d 10.0.0.1/32 -p tcp -m string --string "addons.mozilla." --algo kmp -j REJECT --reject-with tcp-reset

Esto lo que quiere decir es que añada a la cadena de conexiones salientes (-A OUTPUT) una regla que filtre las conexiones con destino al IP 10.0.0.1 (-d 10.0.0.1/32) que es nuestro proxy, por el protocolo TCP (-p tcp) utilizando el módulo de filtrado por cadenas de caracteres (-m string) cualquier paquete que contenga la cadena “addons.mozilla.” (--string "addons.mozilla.") utilizando la estrategia de búsqueda Knuth-Pratt-Morris (--algo kmp), que rechace estos paquetes (-j REJECT) utilizando para ello un paquete de respuesta RST que indica cerrar la conexión (--reject-with tcp-reset). También se podría poner en la regla el puerto destino del proxy si desean ser más específicos (--dport 8080)
Otro ejemplo, los dichosos CDN que me tienen la cuota “derretida”. Supongamos que queremos permitir algunos y denegar al resto:

# iptables -A OUTPUT -d 10.0.0.1/32 -p tcp -m string --string "licdn." --algo kmp -j ACCEPT
# iptables -A OUTPUT -d 10.0.0.1/32 -p tcp -m string --string "fbcdn.net" --algo kmp -j ACCEPT
# iptables -A OUTPUT -d 10.0.0.1/32 -p tcp -m string --string "cdn." --algo kmp -j REJECT --reject-with tcp-reset

Acá permitimos el CDN de LinkeIn, que contiene la cadena de caracteres “licdn.” y uno de los tantos de Facebook que contiene la cadena de caracteres “fbcdn.net” y denegamos cualquier otro dominio que contenga la cadena “cdn.”
Recuerden que siempre que creemos reglas con el comando iptables, las estamos creando directamente en las tablas del núcleo, pero si no las salvamos, las perderemos cuando reiniciemos, así que no olviden salvarlas:

# /etc/init.d/iptables-persistent save

Para más información: man iptables
Esto es todo, espero que les sea util. ;-)