nftables es el framework moderno de clasificación de paquetes en el kernel de Linux, diseñado como sucesor de las herramientas legacy iptables, ip6tables, arptables y ebtables. Desde su introducción en el kernel Linux 3.13, nftables se ha convertido en el backend de firewalling predeterminado en la mayoría de las distribuciones principales de Linux, incluyendo Debian 10+, Ubuntu 20.10+, RHEL 8+ y Fedora 18+. Esta guía proporciona un recorrido completo por los conceptos, sintaxis y configuraciones prácticas de nftables para asegurar servidores Linux, incluyendo NAT, limitación de velocidad, conjuntos, registro y migración desde iptables.

Requisitos Previos

Antes de comenzar, asegúrate de tener:

  • Ubuntu Server 20.04, 22.04 o 24.04 (o cualquier distribución Linux con kernel 3.13 o posterior)
  • Acceso a terminal con privilegios sudo
  • Acceso SSH al servidor (si configuras remotamente)
  • Comprensión básica de puertos TCP/UDP, direccionamiento IP y conceptos de redes
  • Familiaridad con conceptos de iptables (útil pero no obligatorio)

¿Qué es nftables?

nftables es un subsistema del kernel de Linux que proporciona filtrado de paquetes, traducción de direcciones de red (NAT), manipulación de paquetes y clasificación de tráfico con estado. Reemplaza las herramientas legacy de Netfilter (iptables, ip6tables, arptables, ebtables) con un framework único y unificado gestionado a través de la utilidad de línea de comandos nft.

Ventajas clave de nftables sobre iptables:

  • Herramienta unificada — un solo comando nft reemplaza iptables, ip6tables, arptables y ebtables
  • Sintaxis más limpia — formato de reglas más legible y consistente con gramática adecuada
  • Mejor rendimiento — estructuras de datos nativas de conjuntos y mapas para coincidencia eficiente contra grandes listas de IPs, puertos o interfaces
  • Reemplazo atómico de reglas — carga conjuntos de reglas completos atómicamente, previniendo brechas durante actualizaciones
  • Sin tablas ni cadenas predefinidas — creas solo lo que necesitas, reduciendo la sobrecarga
  • Soporte dual-stack integrado — la familia inet maneja tanto IPv4 como IPv6 en una sola tabla

nftables vs iptables

Comprender las diferencias clave ayuda en la transición:

Característicaiptablesnftables
Comandoiptables, ip6tables, arptables, ebtablesnft (herramienta única)
Familias de direccionesHerramienta separada por familiaFamilia inet unificada para IPv4/IPv6
SintaxisBasada en flags (-A, -j, -p)Gramática estructurada (add rule ... accept)
ConjuntosRequiere extensión ipsetConjuntos y mapas nativos integrados
Actualizaciones de reglasInserción/eliminación linealReemplazo atómico vía -f
Cadenas predefinidasCadenas obligatorias (INPUT, OUTPUT, FORWARD)Sin predeterminados; creas tablas y cadenas según necesidad
RendimientoEvaluación lineal de reglasBúsquedas optimizadas en conjuntos, expresiones binarias
Interfaz del kernelxtables (una por herramienta)nf_tables (API unificada)

Instalación de nftables en Ubuntu

En Ubuntu 22.04 y versiones posteriores, nftables está disponible en los repositorios predeterminados. Instálalo:

sudo apt update
sudo apt install nftables

Habilita e inicia el servicio para que las reglas persistan entre reinicios:

sudo systemctl enable nftables
sudo systemctl start nftables

Verifica la instalación:

nft --version

Salida esperada:

nftables v1.0.6 (Lester Gooch #4)

Comprueba el conjunto de reglas actual:

sudo nft list ruleset

Si no se han configurado reglas, la salida estará vacía. Esto es esperado — a diferencia de iptables, nftables comienza sin tablas ni cadenas.

Conceptos Fundamentales

nftables organiza el filtrado de paquetes en una jerarquía de tablas, cadenas y reglas. Comprender esta jerarquía es esencial.

Familias de Direcciones

Cada tabla pertenece a una familia de direcciones que determina qué tráfico procesa:

FamiliaDescripción
ipSolo tráfico IPv4
ip6Solo tráfico IPv6
inetTanto IPv4 como IPv6 (recomendado)
arpProtocolo ARP
bridgeTráfico a nivel de puente
netdevTráfico de ingreso en una interfaz específica

Para la mayoría de las configuraciones de servidor, usa la familia inet para manejar tanto IPv4 como IPv6 con un solo conjunto de reglas.

Tablas

Las tablas son contenedores para cadenas y conjuntos. Tienen un nombre y pertenecen a una familia de direcciones. A diferencia de iptables, no hay tablas predefinidas — las creas según necesidad:

sudo nft add table inet filter
sudo nft add table inet nat

Cadenas

Las cadenas contienen reglas y definen cuándo se evalúan esas reglas. Hay dos tipos:

  • Cadenas base — adjuntas a un hook de Netfilter (input, output, forward, prerouting, postrouting). Son los puntos de entrada para el procesamiento de paquetes.
  • Cadenas regulares — no adjuntas a un hook; se usan como destinos de salto para organizar reglas.

Las cadenas base requieren un tipo, hook y prioridad:

sudo nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }

Reglas

Las reglas son las declaraciones de coincidencia y acción dentro de una cadena. Consisten en expresiones (criterios de coincidencia) y un veredicto (accept, drop, reject, etc.):

sudo nft add rule inet filter input tcp dport 22 accept

Creación de Tablas y Cadenas

Construyamos una configuración de firewall completa paso a paso. Comienza creando la tabla:

sudo nft add table inet filter

Crea las cadenas base con políticas predeterminadas:

# Cadena de entrada: descartar todo el tráfico entrante por defecto
sudo nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }

# Cadena de reenvío: descartar el tráfico reenviado por defecto
sudo nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }

# Cadena de salida: permitir todo el tráfico saliente por defecto
sudo nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }

Lista tus tablas y cadenas para confirmar:

sudo nft list tables
sudo nft list chains

Escritura de Reglas

Aceptar Conexiones Establecidas y Relacionadas

Las primeras reglas en tu cadena de entrada deben aceptar tráfico perteneciente a conexiones establecidas o relacionadas. Esto asegura que el tráfico de retorno para tus conexiones salientes no sea bloqueado:

sudo nft add rule inet filter input ct state established,related accept

Permitir Tráfico de Loopback

Los servicios locales se comunican a través de la interfaz de loopback. Siempre permítela:

sudo nft add rule inet filter input iif lo accept

Descartar Conexiones Inválidas

Descarta paquetes que no forman parte de ninguna conexión conocida:

sudo nft add rule inet filter input ct state invalid drop

Permitir ICMP

Permite ping y otros mensajes ICMP para diagnósticos:

sudo nft add rule inet filter input ip protocol icmp accept
sudo nft add rule inet filter input ip6 nexthdr icmpv6 accept

Permitir Servicios Específicos

Acepta tráfico en puertos específicos:

# Permitir SSH
sudo nft add rule inet filter input tcp dport 22 accept

# Permitir HTTP y HTTPS
sudo nft add rule inet filter input tcp dport { 80, 443 } accept

# Permitir un puerto de aplicación personalizado
sudo nft add rule inet filter input tcp dport 8080 accept

# Permitir un puerto UDP (ej., WireGuard)
sudo nft add rule inet filter input udp dport 51820 accept

Restringir por Dirección de Origen

Permitir SSH solo desde una subred de confianza:

sudo nft add rule inet filter input ip saddr 192.168.1.0/24 tcp dport 22 accept

Rechazar en Lugar de Descartar

Descartar no envía respuesta; rechazar envía un error ICMP de vuelta. Agrega un rechazo como regla final para un comportamiento de red más limpio:

sudo nft add rule inet filter input reject with icmpx type port-unreachable

Ver el Conjunto de Reglas Completo

sudo nft list ruleset

Salida de ejemplo:

table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        ct state established,related accept
        iif "lo" accept
        ct state invalid drop
        ip protocol icmp accept
        ip6 nexthdr ipv6-icmp accept
        tcp dport 22 accept
        tcp dport { 80, 443 } accept
        reject with icmpx type port-unreachable
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Configuración de NAT

nftables maneja NAT a través de una tabla dedicada con cadenas de prerouting y postrouting.

Crear la Tabla NAT y las Cadenas

sudo nft add table inet nat
sudo nft add chain inet nat prerouting { type nat hook prerouting priority -100 \; }
sudo nft add chain inet nat postrouting { type nat hook postrouting priority 100 \; }

NAT de Origen (Masquerade)

Enmascarar el tráfico saliente desde una red interna a través de la interfaz pública del servidor. Esto es común para routers y gateways VPN:

sudo nft add rule inet nat postrouting oif "eth0" masquerade

Para una subred de origen específica:

sudo nft add rule inet nat postrouting ip saddr 10.0.0.0/24 oif "eth0" masquerade

SNAT Estático

Si tu servidor tiene una IP pública estática y quieres definir explícitamente la dirección de origen:

sudo nft add rule inet nat postrouting ip saddr 10.0.0.0/24 oif "eth0" snat to 203.0.113.1

NAT de Destino (Reenvío de Puertos)

Reenviar tráfico entrante en un puerto a un host interno:

# Reenviar puerto 8080 al servidor interno 10.0.0.50:80
sudo nft add rule inet nat prerouting iif "eth0" tcp dport 8080 dnat to 10.0.0.50:80

No olvides permitir el tráfico reenviado en tu tabla de filtrado:

sudo nft add rule inet filter forward ip daddr 10.0.0.50 tcp dport 80 accept
sudo nft add rule inet filter forward ct state established,related accept

Habilitar el Reenvío de IP

NAT requiere que el reenvío de IP esté habilitado en el kernel:

sudo sysctl -w net.ipv4.ip_forward=1

Hazlo persistente:

echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.d/99-nftables.conf
sudo sysctl -p /etc/sysctl.d/99-nftables.conf

Limitación de Velocidad y Seguimiento de Conexiones

Limitar Conexiones Entrantes

Protégete contra ataques de fuerza bruta limitando las tasas de conexión. Por ejemplo, limitar SSH a 5 nuevas conexiones por minuto por IP de origen:

sudo nft add rule inet filter input tcp dport 22 ct state new limit rate 5/minute accept

Para una tolerancia de ráfaga (permitir ráfagas cortas por encima de la tasa):

sudo nft add rule inet filter input tcp dport 22 ct state new limit rate 5/minute burst 10 packets accept

Limitación por Origen con Meters

Los meters (anteriormente llamados conjuntos dinámicos) permiten limitación de velocidad por IP de origen:

sudo nft add rule inet filter input tcp dport 22 ct state new meter ssh-rate { ip saddr limit rate 3/minute burst 5 packets } accept

Esto limita cada IP de origen individual a 3 nuevas conexiones SSH por minuto, con una ráfaga de 5 paquetes.

Estados de Seguimiento de Conexiones

nftables usa el subsistema conntrack para filtrado con estado. Estados disponibles:

EstadoDescripción
newPrimer paquete de una nueva conexión
establishedParte de una conexión ya establecida
relatedRelacionado con una conexión establecida (ej., canal de datos FTP)
invalidNo asociado con ninguna conexión conocida
untrackedExplícitamente omitido por conntrack

Limitar Inundaciones ICMP

sudo nft add rule inet filter input ip protocol icmp limit rate 10/second burst 20 packets accept
sudo nft add rule inet filter input ip protocol icmp drop

Conjuntos y Mapas

Los conjuntos y mapas son una de las características más potentes de nftables, permitiendo coincidencias eficientes contra grandes grupos de valores sin escribir reglas individuales.

Conjuntos Anónimos

Los conjuntos anónimos se definen en línea dentro de una regla:

sudo nft add rule inet filter input tcp dport { 22, 80, 443, 8080 } accept

Conjuntos con Nombre

Los conjuntos con nombre se definen por separado y pueden actualizarse dinámicamente sin modificar las reglas que los referencian:

# Crear un conjunto con nombre para puertos TCP permitidos
sudo nft add set inet filter allowed_ports { type inet_service \; }

# Agregar elementos al conjunto
sudo nft add element inet filter allowed_ports { 22, 80, 443, 8080 }

# Usar el conjunto en una regla
sudo nft add rule inet filter input tcp dport @allowed_ports accept

Actualiza el conjunto sin tocar la regla:

# Agregar un nuevo puerto
sudo nft add element inet filter allowed_ports { 3000 }

# Eliminar un puerto
sudo nft delete element inet filter allowed_ports { 8080 }

Conjuntos de Direcciones IP

# Crear un conjunto para IPs bloqueadas
sudo nft add set inet filter blocked_ips { type ipv4_addr \; }

# Poblar el conjunto
sudo nft add element inet filter blocked_ips { 203.0.113.100, 198.51.100.50, 192.0.2.75 }

# Descartar tráfico de IPs bloqueadas
sudo nft add rule inet filter input ip saddr @blocked_ips drop

Conjuntos con Tiempo de Expiración

Crea conjuntos donde las entradas expiran automáticamente:

sudo nft add set inet filter temp_block { type ipv4_addr \; timeout 1h \; }
sudo nft add element inet filter temp_block { 203.0.113.100 timeout 30m }
sudo nft add rule inet filter input ip saddr @temp_block drop

Mapas para Búsquedas de Veredicto

Los mapas asocian una clave con un veredicto, permitiendo decisiones eficientes por valor:

# Crear un mapa de veredicto basado en puertos
sudo nft add map inet filter port_policy { type inet_service : verdict \; }
sudo nft add element inet filter port_policy { 22 : accept, 80 : accept, 443 : accept, 23 : drop }

# Usar el mapa en una regla
sudo nft add rule inet filter input tcp dport vmap @port_policy

Conjuntos Concatenados

Coincidencia en múltiples campos simultáneamente:

# Crear un conjunto que coincida con combinaciones IP + puerto
sudo nft add set inet filter allowed_access { type ipv4_addr . inet_service \; }
sudo nft add element inet filter allowed_access { 10.0.1.20 . 3306, 10.0.1.21 . 5432 }
sudo nft add rule inet filter input ip saddr . tcp dport @allowed_access accept

Registro de Reglas

nftables proporciona registro flexible para monitoreo y depuración de reglas de firewall.

Registro Básico

Registra paquetes antes de descartarlos:

sudo nft add rule inet filter input tcp dport 23 log prefix \"Telnet attempt: \" drop

Registro con Limitación de Velocidad

Previene la inundación de registros limitando la tasa de registro:

sudo nft add rule inet filter input ct state invalid log prefix \"Invalid packet: \" limit rate 5/minute drop

Niveles de Registro

nftables soporta niveles estándar de syslog:

sudo nft add rule inet filter input tcp dport 22 ct state new log prefix \"SSH connection: \" level info accept

Niveles disponibles: emerg, alert, crit, err, warn, notice, info, debug.

Visualización de Registros

Los registros de nftables se escriben en el registro del kernel. Visualízalos con:

sudo dmesg | grep "nft"
sudo journalctl -k --grep="Telnet attempt"

Para registro persistente, configura rsyslog para escribir mensajes de nftables en un archivo dedicado:

# /etc/rsyslog.d/10-nftables.conf
:msg, contains, "nft" /var/log/nftables.log

Reinicia rsyslog:

sudo systemctl restart rsyslog

Migración desde iptables

Si tienes reglas existentes de iptables, nftables proporciona herramientas para facilitar la migración.

Uso de iptables-translate

El comando iptables-translate convierte reglas individuales de iptables a sintaxis nft:

iptables-translate -A INPUT -p tcp --dport 22 -j ACCEPT

Salida:

nft add rule ip filter INPUT tcp dport 22 counter accept

Traducción de un Conjunto Completo de Reglas

Exporta toda tu configuración de iptables y tradúcela:

iptables-save > /tmp/iptables-rules.txt
iptables-restore-translate -f /tmp/iptables-rules.txt > /tmp/nftables-rules.nft

Revisa el archivo traducido y luego cárgalo:

sudo nft -f /tmp/nftables-rules.nft

Verificación de la Capa de Compatibilidad

Ubuntu moderno usa iptables-nft como backend predeterminado. Verifica qué backend usa tu sistema:

update-alternatives --query iptables

O:

iptables --version

Si ves nf_tables en la salida, tus comandos de iptables ya están siendo traducidos a nftables internamente.

Mejores Prácticas de Migración

  1. Exportar reglas existentes — guarda tus reglas actuales de iptables antes de comenzar
  2. Traducir y revisar — usa iptables-restore-translate y revisa cuidadosamente la salida
  3. Probar en entorno no productivo — aplica las reglas traducidas en un servidor de prueba primero
  4. Limpiar reglas antiguas — una vez confirmadas las reglas nft, limpia iptables con iptables -F
  5. Deshabilitar servicio iptables — detén y deshabilita el servicio iptables para evitar conflictos
  6. Habilitar servicio nftables — asegúrate de que el servicio nftables esté habilitado para persistencia

Carga de Conjuntos de Reglas desde Archivos

Para entornos de producción, gestionar tu conjunto de reglas en un archivo es el enfoque recomendado. Aquí hay una configuración de ejemplo completa:

#!/usr/sbin/nft -f

# Limpiar reglas existentes
flush ruleset

# Definir variables
define WAN_IF = eth0
define LAN_IF = eth1
define LAN_NET = 10.0.0.0/24
define ALLOWED_TCP = { 22, 80, 443 }

table inet filter {
    set blocked_ips {
        type ipv4_addr
        elements = { 203.0.113.100, 198.51.100.50 }
    }

    chain input {
        type filter hook input priority 0; policy drop;

        # Seguimiento de conexiones
        ct state established,related accept
        ct state invalid drop

        # Loopback
        iif lo accept

        # Descartar IPs bloqueadas
        ip saddr @blocked_ips drop

        # ICMP
        ip protocol icmp limit rate 10/second accept
        ip6 nexthdr ipv6-icmp limit rate 10/second accept

        # Servicios permitidos con limitación de velocidad en SSH
        tcp dport 22 ct state new limit rate 5/minute burst 10 packets accept
        tcp dport { 80, 443 } accept

        # Rechazo final
        reject with icmpx type port-unreachable
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
        ct state established,related accept
    }

    chain output {
        type filter hook output priority 0; policy accept;
    }
}

Guárdalo en /etc/nftables.conf y cárgalo:

sudo nft -f /etc/nftables.conf

Verifica:

sudo nft list ruleset

Referencia de Comandos nft

ComandoDescripción
nft list rulesetMostrar el conjunto de reglas completo
nft list tablesListar todas las tablas
nft list table inet filterMostrar reglas en una tabla específica
nft list chainsListar todas las cadenas
nft list chain inet filter inputMostrar reglas en una cadena específica
nft list setsListar todos los conjuntos con nombre
nft add table inet <nombre>Crear una nueva tabla
nft delete table inet <nombre>Eliminar una tabla y todo su contenido
nft flush table inet <nombre>Eliminar todas las reglas de una tabla
nft add chain inet <tabla> <cadena> { type filter hook input priority 0 \; }Crear una cadena base
nft add rule inet <tabla> <cadena> <expresión> <veredicto>Agregar una regla al final de una cadena
nft insert rule inet <tabla> <cadena> <expresión> <veredicto>Insertar una regla al inicio de una cadena
nft delete rule inet <tabla> <cadena> handle <n>Eliminar una regla por su número de handle
nft add set inet <tabla> <nombre> { type <tipo> \; }Crear un conjunto con nombre
nft add element inet <tabla> <nombre> { <elementos> }Agregar elementos a un conjunto
nft flush rulesetEliminar todas las tablas, cadenas y reglas
nft -f <archivo>Cargar un conjunto de reglas desde un archivo
nft monitorObservar cambios en el conjunto de reglas en tiempo real

Solución de Problemas

Las Reglas No Surten Efecto

Verifica que el conjunto de reglas esté cargado:

sudo nft list ruleset

Comprueba que tus cadenas estén adjuntas a los hooks correctos y tengan la prioridad esperada:

sudo nft list chains

Asegúrate de que no haya reglas conflictivas de iptables:

sudo iptables -L -n

Bloqueo de Acceso SSH

Si pierdes acceso SSH después de aplicar reglas:

  1. Accede al servidor a través de una consola (consola web del proveedor de nube, KVM o acceso físico)
  2. Limpia todas las reglas: sudo nft flush ruleset
  3. Verifica que el acceso se haya restaurado
  4. Reconstruye tus reglas, asegurándote de que SSH esté permitido antes de establecer una política de descarte

Depuración de Coincidencia de Reglas

Agrega contadores a las reglas para ver cuáles coinciden con el tráfico:

sudo nft add rule inet filter input tcp dport 22 counter accept

Ver contadores:

sudo nft list chain inet filter input

La salida del contador muestra paquetes y bytes coincidentes:

tcp dport 22 counter packets 150 bytes 12000 accept

Las Reglas No Persisten Tras el Reinicio

Asegúrate de que el servicio nftables esté habilitado:

sudo systemctl enable nftables

Guarda el conjunto de reglas actual:

sudo nft list ruleset | sudo tee /etc/nftables.conf

Verifica que el archivo de configuración sea sintácticamente válido:

sudo nft -c -f /etc/nftables.conf

Problemas con Módulos del Kernel

Si los comandos nft fallan, verifica que los módulos del kernel requeridos estén cargados:

lsmod | grep nf_tables

Cárgalos manualmente si es necesario:

sudo modprobe nf_tables
sudo modprobe nft_chain_nat

Resumen

nftables es el reemplazo definitivo de iptables en sistemas Linux modernos. Su interfaz de comandos unificada, soporte nativo de conjuntos y mapas, reemplazo atómico de reglas y sintaxis más limpia lo convierten en una mejora significativa sobre el conjunto de herramientas legacy. Ya sea que estés configurando un firewall de host simple o un gateway NAT complejo con limitación de velocidad y conjuntos dinámicos, nftables proporciona las herramientas para construir configuraciones de firewall eficientes y mantenibles.

Puntos clave:

  • Usa la familia inet para manejar tanto IPv4 como IPv6 en una sola tabla
  • Siempre permite conexiones establecidas/relacionadas y tráfico de loopback primero
  • Aprovecha los conjuntos con nombre para gestionar listas dinámicas de IPs y puertos sin reescribir reglas
  • Usa limitación de velocidad en servicios de autenticación como SSH para mitigar ataques de fuerza bruta
  • Gestiona tu conjunto de reglas en un archivo y cárgalo atómicamente con nft -f
  • Habilita el servicio systemd de nftables para persistencia entre reinicios
  • Usa iptables-translate e iptables-restore-translate para migrar conjuntos de reglas existentes

Para una experiencia de gestión de firewall de nivel superior en Ubuntu, consulta nuestra guía sobre Configuración del Firewall UFW en Ubuntu Server. Para complementar tu firewall con acceso remoto seguro, consulta Hardening SSH para Servidores Linux.