Configura el firewall Ferm, un frontend de iptables en tu servidor Linux

En sistemas operativos basados en Linux, el firewall por excelencia que utilizas es iptables, no obstante, también es posible que utilices nftables que es la evolución de iptables mucho más eficiente y con una sintaxis mucho más «humana», sin embargo, no todo el mundo utiliza todavía nftables. Hoy os vamos a explicar cómo configurar un firewall en servidores Linux haciendo uso de Ferm (For Easy Rule Making), un frontend de iptables que nos permitirá añadir reglas al firewall de manera muy fácil, rápida y sencilla, sin tener que aprendernos la sintaxis de iptables.

¿Qué es el firewall Ferm y para qué sirve?

Ferm (For Easy Rule Making) es un frontend de iptables, esto significa que, por debajo, realmente está utilizando iptables para permitir o denegar el tráfico, pero nos permite configurar de forma muy avanzada el firewall sin necesidad de aprendernos la sintaxis de iptables ni realizar diferentes scripts haciendo uso de iptables, sino que lo haremos directamente con Ferm. Esta herramienta es capaz de leer las reglas de un archivo de configuración que nosotros vamos a definir, y posteriormente «llamará» a iptables para ir añadiendo las diferentes reglas una a una, insertándose en tiempo real en el kernel.

El objetivo de Ferm es proporcionar a los administradores de sistemas y redes una forma fácil de leer y escribir todas las reglas del cortafuegos, reduciendo la tarea de tener que escribir una regla tras otra, por lo que podremos dedicar más tiempo al desarrollo y optimización de las reglas, para que sean lo más eficientes posible. Ferm utiliza un lenguaje de configuración muy simple pero bastante avanzado, podremos utilizar variables, funciones, arrays e incluso bloques. Otras opciones muy interesantes de Ferm es que nos permitirá incluir otros archivos de configuración en un directorio, y se encargará de importar y aplicar todas esas reglas de forma automática.

Ferm no deja de ser un frontend de iptables, por tanto, cuando utilicemos esta herramienta, siempre vamos a poder editar y configurar directamente el firewall haciendo uso de los comandos de iptables. De hecho, Ferm es capaz de importar las reglas actuales de iptables y ponerlas automáticamente en el archivo de configuración, para posteriormente editarlas o ampliarlas.

Uno de los frontend de iptables más populares es ufw, ampliamente utilizado por los administradores de sistemas y redes para configurar de manera fácil y rápida sus firewalls.

Instalación y puesta en marcha de Ferm

La instalación de Ferm es realmente sencilla, actualmente se encuentra en la mayoría de repositorios de las diferentes distribuciones basadas en Linux, en nuestro caso hemos utilizado la última versión de Debian para realizar todas las pruebas que os vamos a enseñar. Para instalar este programa que es un frontend de iptables, debemos ejecutar la siguiente orden:

sudo apt install ferm

Una vez que ejecutemos esta orden, deberíamos ver algo como esto, donde se nos mostrará los paquetes adicionales que tenemos que instalar, básicamente tenemos que instalar Perl para poder ejecutar correctamente este programa.

El instalador de Ferm nos va a indicar que cargará las reglas del firewall durante el arranque desde la ruta /etc/ferm/ferm.conf, es decir, todo lo que haya en este archivo se pasará automáticamente a iptables para permitir o denegar el tráfico de red. La configuración predeterminada de este firewall nos permite tener acceso por SSH de forma remota a través del puerto 22, si no tienes el SSH configurado en este puerto, entonces tendrás que editar los valores por defecto y pulsar sobre «no» para que no arranque, de lo contrario, perderás la conectividad.

Una vez que hayamos elegido sí o no, apt se encargará de terminar de instalar todos los paquetes adicionales que necesitamos para hacer funcionar este programa.

Una vez instalado, podremos irnos a la ruta de /etc/ferm/ y veremos tanto el archivo de configuración llamado ferm.conf, como también un directorio llamado ferm.d donde podremos incorporar nuestros archivos de configuración de ferm para importarlos, esto nos permite tener una mayor modularidad.

Ferm ya viene de forma predeterminada con una lista de reglas que podemos eliminar en cualquier momento, pero esto nos ayudará a tratar con la sintaxis de este frontend de iptables, por tanto, nos servirá de bastante ayuda. Si nos fijamos en la sintaxis, veremos que es similar a nftables, pero está basado en iptables.

En la siguiente captura podéis ver cómo se declaran los dominios donde se va a configurar (iptables o ip6tables), las tablas y las cadenas, así como las reglas que tenemos dentro de las diferentes cadenas.

También podremos ver que disponemos de varias reglas de forma predeterminada:

  • En la cadena INPUT la política es de DROP, se permite tráfico a localhost, tráfico ICMP y se permite la conexión vía IPsec y también vía SSH con los puertos predeterminados. Respecto al estado de las conexiones, se hace un DROP de las conexiones inválidas, y se permiten las establecidas y relacionadas, pero no se permiten las nuevas, excepto las definidas específicamente.

En la cadena de OUTPUT se define que la política es de aceptar todo, y el estado de la conexión se permiten las establecidas y relacionadas. En la cadena de FORWARD se deniega el tráfico por política, se bloquean específicamente las conexiones inválidas pero sí se permiten las conexiones establecidas y relacionadas.

A continuación, podéis ver este fichero de configuración en formato texto:

# -*- shell-script -*-
#
# Configuration file for ferm(1).
#
domain (ip ip6) {
table filter {
chain INPUT {
policy DROP;

# connection tracking
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;

# allow local packet
interface lo ACCEPT;

# respond to ping
proto icmp ACCEPT;

# allow IPsec
proto udp dport 500 ACCEPT;
@if @eq($DOMAIN, ip) {
proto (esp ah) ACCEPT;
} @else {
proto (esp) ACCEPT;
}

# allow SSH connections
proto tcp dport ssh ACCEPT;
}
chain OUTPUT {
policy ACCEPT;

# connection tracking
#mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
}
chain FORWARD {
policy DROP;

# connection tracking
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
}
}
}

@include ferm.d/;

La parte más interesante es el «@include ferm.d/» que tenemos en la parte final, esto significa que va a importar todos los archivos de configuración que tengamos en ese directorio en cuestión.

Este firewall de Ferm por debajo utiliza iptables, por tanto, si ejecutamos la siguiente orden:

iptables -L

Podremos ver el estado actual de iptables con todas las reglas que ha incorporado en el cortafuegos:

Una vez que hemos visto la configuración predeterminada de Ferm, vamos a ver diferentes ejemplos de configuración que podemos hacer.

Configuración básica de Ferm

La sintaxis de Ferm es muy simple y flexible, pero debemos aprenderla para realizar una configuración correcta.  Os recomendamos acceder al manual oficial de Ferm donde encontraréis todos los detalles sobre la sintaxis a utilizar y cómo se deben declarar las diferentes reglas en el archivo de configuración, gracias a este manual oficial podremos configurar este firewall sin muchos problemas.

Lo primero que debemos tener en cuenta es que todas las reglas de Ferm se empiezan y terminan con llaves, y las reglas terminan con punto y coma, por tanto, es una sintaxis bastante conocida en programación. Otras características interesantes son que se ignoran los saltos de línea, y se pueden poner comentarios en cualquier sitio poniendo «#» hasta el final de línea.

Respecto a la sintaxis de iptables y ferm, tenemos algunas diferencias:

  • Para definir interfaz de entrada: interface (if)
  • Para definir interfaz de salida: outerface (of)
  • Para definir un origen: saddr
  • Para definir un destino: daddr
  • Para definir un protocolo: proto
  • Puerto de origen: sport
  • Puerto de destino: dport
  • Cargar un módulo: mod
  • Saltar a una regla personalizada: jump

En Ferm no existen comandos como -A, -I, -C, -R o -D, ya que todo está escrito en un archivo de configuración, lo mismo ocurre con los comandos para añadir una nueva cadena, renombrarla o eliminarla, ahora aquí desaparece por completo. Otras características son que ferm permite heredar diferentes reglas para usarlas dentro de otras reglas, anidando en el archivo de configuración.

Una vez que conocemos a grandes rasgos cómo es la sintaxis, vamos a ver algunos ejemplos comparándolo con iptables, en todos ellos trabajaremos en la tabla «filter» en la cadena «INPUT».

iptables -P INPUT ACCEPT
iptables -A INPUT -p tcp -j ACCEPT

En ferm esto se escribiría de la siguiente forma (añadiendo la política de la cadena OUTPUT y FORWARD de la tabla filter):

domain ip {
table filter {
chain INPUT {
policy DROP;
proto tcp ACCEPT;
}
chain OUTPUT {
policy ACCEPT;
}
chain FORWARD {
policy DROP;
}
}
}

Ferm nos permite definir las mismas reglas en el INPUT y OUTPUT de forma fácil y rápida, sin necesidad de repetir las reglas una y otra vez. Por ejemplo, imaginemos que ahora queremos aceptar el protocolo TCP tanto en la cadena INPUT como en OUTPUT, esto en iptables sería de la siguiente forma:

iptables -A INPUT -p tcp -j ACCEPT
iptables -A OUTPUT -p tcp -j ACCEPT
iptables -A INPUT -p udp -j ACCEPT
iptables -A OUTPUT -p udp -j ACCEPT

Con Ferm es tan sencillo como hacer lo siguiente:

domain ip {
table filter {
chain (INPUT OUTPUT) {
proto (udp tcp) ACCEPT;
}
}

Tal y como podéis ver, es mucho más rápido y sencillo aplicar esta misma regla tanto en el INPUT como en el OUTPUT.

Este firewall también incorpora funciones muy interesantes, por ejemplo, podremos comprobar si una variable o función está definida, podremos comprobar si dos valores son iguales o diferentes, negar un valor booleano, resolver dominios directamente desde Ferm, concatenar parámetros y un largo etcétera de funciones.

Ferm también permite «cargar» los módulos de iptables para utilizarlos, y configurar el firewall de forma avanzada, por ejemplo, tenemos lo siguiente:

mod connlimit connlimit-above 4 connlimit-mask 24 REJECT;

Que podremos poner a lo largo de todo el archivo de configuración.

Para aplicar las reglas introducidas en Ferm, tendremos que ejecutar el siguiente comando:

ferm -i -t 10 /etc/ferm/ferm.conf

Importar las reglas de iptables en Ferm

Ferm nos permite importar de manera fácil y rápida las reglas de iptables que tenemos actualmente en ejecución, en un archivo de Ferm para su posterior modificación. Para poder realizar esto, simplemente tendremos que tener las reglas de iptables cargadas en memoria (en uso actualmente) y ejecutar esta orden:

import-ferm > /etc/ferm/ferm.d/reglas-iptables.conf

Al ejecutarlo, podremos ver las reglas de iptables directamente en sintaxis de Ferm.

Si quieres transformar las reglas de iptables que tienes en un archivo de texto a Ferm, podrás ejecutar el comando siguiente:

import-ferm origen de las reglas de iptables > /etc/ferm/ferm.d/reglas-iptables.conf

Tal y como habéis visto, ferm es un gran frontend de iptables que nos permitirá configurarlo de forma avanzada, sin necesidad de aprendernos la sintaxis de iptables y organizar las reglas correctamente en un fichero de configuración. No obstante, en nuestra opinión, creemos que configurando un script en bash con todas las reglas de iptables correctamente no es necesario ningún tipo de frontend ni software adicional, aunque es posible que a algunas personas les sea de utilidad. Debemos recordar que Nftables ya incorpora la posibilidad de configurar las reglas directamente en un archivo de configuración, y no solamente de forma interactiva a través de comandos por consola.

¡Sé el primero en comentar!