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
nftreemplaza 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
inetmaneja tanto IPv4 como IPv6 en una sola tabla
nftables vs iptables
Comprender las diferencias clave ayuda en la transición:
| Característica | iptables | nftables |
|---|---|---|
| Comando | iptables, ip6tables, arptables, ebtables | nft (herramienta única) |
| Familias de direcciones | Herramienta separada por familia | Familia inet unificada para IPv4/IPv6 |
| Sintaxis | Basada en flags (-A, -j, -p) | Gramática estructurada (add rule ... accept) |
| Conjuntos | Requiere extensión ipset | Conjuntos y mapas nativos integrados |
| Actualizaciones de reglas | Inserción/eliminación lineal | Reemplazo atómico vía -f |
| Cadenas predefinidas | Cadenas obligatorias (INPUT, OUTPUT, FORWARD) | Sin predeterminados; creas tablas y cadenas según necesidad |
| Rendimiento | Evaluación lineal de reglas | Búsquedas optimizadas en conjuntos, expresiones binarias |
| Interfaz del kernel | xtables (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:
| Familia | Descripción |
|---|---|
ip | Solo tráfico IPv4 |
ip6 | Solo tráfico IPv6 |
inet | Tanto IPv4 como IPv6 (recomendado) |
arp | Protocolo ARP |
bridge | Tráfico a nivel de puente |
netdev | Trá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:
| Estado | Descripción |
|---|---|
new | Primer paquete de una nueva conexión |
established | Parte de una conexión ya establecida |
related | Relacionado con una conexión establecida (ej., canal de datos FTP) |
invalid | No asociado con ninguna conexión conocida |
untracked | Explí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
- Exportar reglas existentes — guarda tus reglas actuales de iptables antes de comenzar
- Traducir y revisar — usa
iptables-restore-translatey revisa cuidadosamente la salida - Probar en entorno no productivo — aplica las reglas traducidas en un servidor de prueba primero
- Limpiar reglas antiguas — una vez confirmadas las reglas nft, limpia iptables con
iptables -F - Deshabilitar servicio iptables — detén y deshabilita el servicio iptables para evitar conflictos
- 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
| Comando | Descripción |
|---|---|
nft list ruleset | Mostrar el conjunto de reglas completo |
nft list tables | Listar todas las tablas |
nft list table inet filter | Mostrar reglas en una tabla específica |
nft list chains | Listar todas las cadenas |
nft list chain inet filter input | Mostrar reglas en una cadena específica |
nft list sets | Listar 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 ruleset | Eliminar todas las tablas, cadenas y reglas |
nft -f <archivo> | Cargar un conjunto de reglas desde un archivo |
nft monitor | Observar 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:
- Accede al servidor a través de una consola (consola web del proveedor de nube, KVM o acceso físico)
- Limpia todas las reglas:
sudo nft flush ruleset - Verifica que el acceso se haya restaurado
- 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
inetpara 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-translateeiptables-restore-translatepara 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.