Primeros pasos en nftables: resolviendo un caso práctico

Publicado por Diego Córdoba el

Hoy vamos a dar nuestros primeros pasos en nftables adentrándonos en las configuraciones persistentes del firewall en Debian, resolviendo un pequeño caso práctico.

El esquema de red del ejemplo

Supongamos el siguiente esquema de red:

  • Un cliente que se conecta a Internet por medio de un router/firewall Linux.
  • El cliente tiene la dirección IP 192.168.20.100, y usa como puerta de enlace predeterminada (default gateway) al router/firewall.
  • El router/firewall dispone de dos interfaces de red:
    • enp2s0, conectada al cliente, con IP 192.168.20.1
    • ens1, conectada a Internet, con una dirección IP pública.
primeros pasos en nftables: diagrama de ejemplo

Vamos a realizar las siguientes configuraciones en nuestro router/firewall con nftables:

  • Configurar el firewall GNU/Linux como router (reglas NAT incluidas)
  • Crear la tabla filter
  • Crear las cadenas input, output y forward en la tabla filter
  • Denegar todo el tráfico en las tres cadenas de manera predeterminada
  • Habilitar el tráfico input/output en la interfaz de loopback
  • Crear las reglas de manejo de estado de conexiones (firewall stateful)
  • Habilitar al cliente para que pueda navegar en Internet (http/https, dns)
  • Habilitar al cliente para que pueda conectarse al firewall via SSH
  • Habilitar al cliente para que pueda hacer ping al exterior, sólo con fines de debugging.

Con estas configuraciones tocamos varias cosas de networking y nftables… por supuesto, le daremos un pequeño valor añadido con variables y comentarios 🙂

¿Querés saber más de Redes TCP/IP y protocolos de Internet?
Sumate a nuestro curso 📚!

Linux como router!

Esto ya lo hemos visto con anterioridad, así que les comparto el artículo en el blog, y el video en youtube para que puedan cumplimentar este paso 🙂

Tablas, cadenas y reglas

En esta oportunidad vamos a dar nuestros primeros pasos en nftables de manera perrsistente, no vamos a detallar cada uno de los comandos para crear cada cosa manualmente (ya hemos visto algo de eso antes), sino que vamos ha hacerlo editando un archivo de configuración.

En esta configuración tendremos lo siguiente:

  • Una tabla filter con:
    • Una cadena INPUT con política por default a DROP, con:
      • Una rergla para aceptar conexiones establecidas y relacionadas (stateful).
      • Una regla para aceptar el tráfico loopback de entrada.
      • Una regla para aceptar el tráfico entrante TCP 22 (SSH).
    • Una cadena OUTPUT con política por default a DROP, con:
      • Una rergla para aceptar conexiones establecidas y relacionadas.
      • Una regla para aceptar el tráfico loopback de salida.
    • Una cadena FORWARD con política por default a DROP, con:
      • Una rergla para aceptar conexiones establecidas y relacionadas.
      • Una regla para aceptar tráfico TCP 80/443 (HTTP/HTTP) desde la LAN.
      • Una regla para aceptar tráfico UDP 53 (DNS) desde la LAN.
      • Una regla para aceptar tráfico ICMP (ping) desde la LAN, para depuración.
  • Una tabla NAT con:
    • Una cadena POSTROUTING con:
      • Una regla para enmascarar todo el tráfico saliente hacia Internet.

A esto vamos a sumarle algunas funcionalidades de nftables, como:

  • Uso de comentarios para documentar la configuración.
  • Uso de variables para parametrizar las reglas.

El script completo

Aquí va el script de configuración. En este caso fue un Debian 12, por lo que el script se encuentra en /etc/nftables.conf.

#!/usr/sbin/nft -f

# limpiamos las reglas
flush ruleset

# Definimos algunas variables
define LAN = 192.168.20.0/24
define POLICY = "drop"
define OIF = "ens1"

# Tabla Filter
table inet filter {

	# cadena INPUT con policy default a drop
	chain input {
		type filter hook input priority filter;
		policy $POLICY

		# stateful
		ct state {established,related} accept

		# aceptamos tráfico loopback para que no explote todo
		iifname "lo" accept

		# SSH desde la LAN
		ip saddr $LAN tcp dport 22 accept
	}

	# cadena FORWARD con policy default a drop
	chain forward {
		type filter hook forward priority filter;
		policy $POLICY

		# stateful
		ct state {established,related} accept

		# ping desde la LAN a Internet (testing)
		ip saddr $LAN icmp type echo-request accept

		# HTTP/HTTPS desde la LAN a Internet
		ip saddr $LAN tcp dport {80,443} accept

		# DNS desde la LAN a Internet
		ip saddr $LAN udp dport 53 accept

	}

	# cadena OUTPUT con policy default a drop
	chain output {
		type filter hook output priority filter;
		policy $POLICY
		
		# stateful
		ct state {established,related} accept

		# aceptamos tráfico loopback para que no explote todo
		oifname "lo" accept
	}
}

# Tabla NAT
table ip nat {
	
	# Cadna POSTROUTING
	chain postrouting {
		type nat hook postrouting priority srcnat; policy accept;

		# masquerade del tráfico de la LAN a Internet
		ip saddr $LAN oifname $OIF masquerade
	}
}

Como se ve, he parametrizado direcciones IP de la LAN, nombre de la interfaz de red de salida, y la policy por default. Esto me permite cambiar todas las policies predeterminadas modificando el valor de una variable, muy útil cuando estamos aprendiendo, y queremos cambiar el comportamiento con poco esfuerzo.

Primeros pasos en nftables: ¿se puede hacer más?

La intención de este post es que demos nuestros primeros pasos en nftables, que veamos una manera de configurarlo de forma simple, y nos deje un firewall funcional y persistente.

¿Podría haberse hecho de otra forma? ¿Podría ser mejor?

Sí, por supuesto, entre otras:

  • Podríamos haber organizado mejor las tablas en diferentes archivos de configuración, facilitando el mantenimiento de las configuraciones.
  • Podríamos también haber añadido contadores de tráfico para mantener estadísticas.
  • Podríamos haber incluido comentarios dentro de las reglas para verlos en un list ruleset.

Pero esto vamos a dejarlo para más adelante, o para que puedan verlo directamente en el curso, al igual que los comandos detallados y otras curiosidades 😜

En poco tiempo tendremos el curso de Nftables online para que puedan seguir aprendiendo esto y mucho más!

Y sí, este artículo será publicado en el canal de Youtube como video, para que veamos paso a paso las configuraciones y sus detalles, no olviden seguirnos para enterarse!

Hasta la próxima!


¿Querés aprender más? 📚

👉 Visitá nuestros cursos!
💬 Y si tenés dudas, o querés dejarnos tus comentarios sumate a la Comunidad JuncoTIC en Telegram!
¡Te esperamos!

Categorías: Sin categoría

Diego Córdoba

- Ingeniero en Informática - Mgtr. Teleinformática - Instructor GNU/Linux, Programación, Redes TCP/IP, criptografía y ciberseguridad. - (Ex) Docente universitario e investigador