Configuración de nftables (Sucesor de iptables): Guía Completa

Introducción

nftables representa la evolución moderna del filtrado de paquetes en Linux, diseñado como sucesor de los venerables frameworks iptables, ip6tables, arptables y ebtables. Introducido en el kernel de Linux 3.13 y alcanzando madurez en años recientes, nftables ofrece un enfoque unificado, simplificado y más poderoso para el filtrado de paquetes y la traducción de direcciones de red. A diferencia de las herramientas legacy fragmentadas que requerían utilidades separadas para filtrado IPv4, IPv6, ARP y bridge, nftables proporciona una única interfaz de línea de comandos (nft) y una sintaxis de conjunto de reglas cohesiva que maneja todos los escenarios de filtrado de paquetes.

nftables aborda muchas limitaciones de iptables mientras mantiene conceptos similares, haciendo la transición manejable para administradores experimentados. Las mejoras clave incluyen mejor rendimiento a través de comunicación reducida kernel-espacio de usuario, sintaxis mejorada con variables y diccionarios, mejor soporte dual-stack IPv4/IPv6, actualizaciones atómicas de conjunto de reglas y un lenguaje de configuración más lógico y legible por humanos. Las principales distribuciones de Linux incluyendo Debian 10+, Ubuntu 20.04+, RHEL 8+ y Rocky Linux 8+ han adoptado nftables como su backend de firewall por defecto.

Esta guía exhaustiva cubre nftables desde conceptos fundamentales hasta configuraciones avanzadas, incluyendo estructura de conjunto de reglas, tipos de familia, organización de tablas y cadenas, implementación NAT, registro, optimización de rendimiento y estrategias de migración desde iptables. Ya sea que estés desplegando nftables en sistemas nuevos o migrando configuraciones iptables existentes, esta guía proporciona el conocimiento necesario para aprovechar este poderoso framework de filtrado de paquetes.

Entendiendo la Arquitectura de nftables

¿Por Qué nftables?

Ventajas sobre iptables:

  • Framework unificado - Herramienta única para filtrado IPv4, IPv6, ARP y bridge
  • Sintaxis simplificada - Reglas más legibles y mantenibles
  • Mejor rendimiento - Comunicación reducida kernel-espacio de usuario
  • Actualizaciones atómicas - Todos los cambios de reglas aplicados atómicamente
  • Variables incorporadas - Conjuntos, mapas y diccionarios para coincidencia compleja
  • Depuración mejorada - Mejores mensajes de error y rastreo
  • Base de código más pequeña - Implementación de kernel más mantenible

Componentes de nftables

1. Tablas

  • Contenedores para cadenas
  • Definidas por familia (ip, ip6, inet, arp, bridge, netdev)

2. Cadenas

  • Listas de reglas
  • Pueden ser cadenas base (enganchadas a netfilter) o cadenas regulares

3. Reglas

  • Criterios de coincidencia y veredicto (accept, drop, reject, etc.)
  • Procesadas secuencialmente dentro de cadenas

4. Conjuntos y Mapas

  • Colecciones nombradas para coincidencia eficiente
  • Diccionarios para mapeo de valores

Tipos de Familia

# ip - Paquetes IPv4
# ip6 - Paquetes IPv6
# inet - Tanto IPv4 como IPv6 (dual-stack)
# arp - Paquetes ARP
# bridge - Tráfico bridge
# netdev - Tráfico ingress (filtrado temprano)

Tipos de Hook

Hooks de cadena base:

ingress - Etapa muy temprana (solo familia netdev)
prerouting - Antes de decisión de enrutamiento
input - Para proceso local
forward - Para paquetes enrutados
output - Desde proceso local
postrouting - Después de decisión de enrutamiento

Prerrequisitos

Antes de configurar nftables, asegúrate de tener:

  • Sistema Linux con kernel 3.13+ (4.x+ recomendado)
  • Acceso root o sudo
  • Paquete nftables instalado
  • Comprensión básica de conceptos de filtrado de paquetes
  • Conocimiento de tu topología de red
  • Acceso SSH o consola (crítico para recuperación)

Instalación

Debian/Ubuntu:

sudo apt update
sudo apt install nftables -y

RHEL/CentOS/Rocky Linux 8+:

sudo dnf install nftables -y

Habilitar servicio nftables:

sudo systemctl enable nftables
sudo systemctl start nftables

Verificar Instalación

# Verificar versión
nft --version

# Listar conjunto de reglas actual
sudo nft list ruleset

# Verificar estado del servicio
sudo systemctl status nftables

Comandos Básicos de nftables

Ver Conjuntos de Reglas

# Listar conjunto de reglas completo
sudo nft list ruleset

# Listar tabla específica
sudo nft list table inet filter

# Listar cadena específica
sudo nft list chain inet filter input

# Listar con handles (para eliminación de reglas)
sudo nft -a list ruleset

Crear Tablas y Cadenas

# Crear tabla
sudo nft add table inet filter

# Crear cadena base
sudo nft add chain inet filter input '{ type filter hook input priority 0; policy accept; }'

# Crear cadena regular
sudo nft add chain inet filter custom_chain

Agregar Reglas

# Agregar regla al final de cadena
sudo nft add rule inet filter input tcp dport 22 accept

# Insertar regla al principio
sudo nft insert rule inet filter input tcp dport 22 accept

# Agregar regla en posición específica
sudo nft insert rule inet filter input position 5 tcp dport 22 accept

Eliminar Reglas

# Eliminar regla por handle
sudo nft delete rule inet filter input handle 5

# Eliminar cadena completa
sudo nft delete chain inet filter input

# Eliminar tabla completa
sudo nft delete table inet filter

# Vaciar todas las reglas en cadena
sudo nft flush chain inet filter input

# Vaciar todas las reglas en tabla
sudo nft flush table inet filter

# Vaciar conjunto de reglas completo
sudo nft flush ruleset

Configuración Básica de Firewall

Ejemplo Simple de Firewall

#!/usr/sbin/nft -f

# Vaciar conjunto de reglas existente
flush ruleset

# Crear tabla inet (maneja tanto IPv4 como IPv6)
table inet filter {
    # Cadena input
    chain input {
        type filter hook input priority 0; policy drop;

        # Permitir loopback
        iif lo accept

        # Permitir conexiones establecidas y relacionadas
        ct state established,related accept

        # Descartar paquetes inválidos
        ct state invalid drop

        # Permitir SSH
        tcp dport 22 accept

        # Permitir HTTP y HTTPS
        tcp dport { 80, 443 } accept

        # Permitir ping
        icmp type echo-request limit rate 1/second accept
        icmpv6 type echo-request limit rate 1/second accept

        # Registrar paquetes descartados
        limit rate 5/minute log prefix "nftables input drop: "
    }

    # Cadena forward (para routers)
    chain forward {
        type filter hook forward priority 0; policy drop;
    }

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

Guardar como /etc/nftables.conf y aplicar:

sudo nft -f /etc/nftables.conf
sudo systemctl reload nftables

Configuración de Servidor Web

#!/usr/sbin/nft -f

flush ruleset

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

        # Loopback
        iif lo accept

        # Conexiones establecidas
        ct state established,related accept
        ct state invalid drop

        # SSH desde subred específica
        ip saddr 192.168.1.0/24 tcp dport 22 accept

        # Servicios web
        tcp dport { 80, 443 } accept

        # ICMP
        ip protocol icmp icmp type { echo-request, echo-reply } limit rate 1/second accept
        ip6 nexthdr icmpv6 icmpv6 type { echo-request, echo-reply } limit rate 1/second accept

        # Registrar y descartar
        limit rate 5/minute log prefix "nftables drop: "
    }

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

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

Características Avanzadas

Conjuntos para Coincidencia Eficiente

Conjuntos nombrados:

# Crear tabla y cadena
nft add table inet filter
nft add chain inet filter input '{ type filter hook input priority 0; policy drop; }'

# Crear conjunto de IPs permitidas
nft add set inet filter allowed_ips '{ type ipv4_addr; }'

# Agregar elementos al conjunto
nft add element inet filter allowed_ips { 192.168.1.10, 192.168.1.20, 192.168.1.30 }

# Usar conjunto en regla
nft add rule inet filter input ip saddr @allowed_ips accept

Conjuntos anónimos en línea:

# Permitir múltiples puertos
nft add rule inet filter input tcp dport { 22, 80, 443, 8080 } accept

# Bloquear múltiples IPs
nft add rule inet filter input ip saddr { 10.0.0.1, 10.0.0.2 } drop

Intervalos en conjuntos:

# Crear conjunto con soporte de intervalo
nft add set inet filter blocked_ranges '{ type ipv4_addr; flags interval; }'

# Agregar rangos de IP
nft add element inet filter blocked_ranges { 192.168.1.1-192.168.1.50, 10.0.0.0/8 }

# Usar en regla
nft add rule inet filter input ip saddr @blocked_ranges drop

Mapas (Diccionarios)

Mapeo de puertos:

# Crear mapa
nft add map inet nat portmap '{ type inet_service : ipv4_addr; }'

# Agregar mapeos de puerto a IP
nft add element inet nat portmap { 80 : 192.168.1.10, 443 : 192.168.1.20 }

# Usar en regla DNAT
nft add rule inet nat prerouting dnat to tcp dport map @portmap

Mapas de veredicto:

# Crear mapa de veredicto
nft add map inet filter ip_actions '{ type ipv4_addr : verdict; }'

# Definir acciones por IP
nft add element inet filter ip_actions { 192.168.1.10 : accept, 192.168.1.20 : drop }

# Usar en regla
nft add rule inet filter input ip saddr vmap @ip_actions

Variables

#!/usr/sbin/nft -f

# Definir variables
define WAN_IF = eth0
define LAN_IF = eth1
define SSH_PORT = 22
define WEB_PORTS = { 80, 443 }
define TRUSTED_IPS = { 192.168.1.10, 192.168.1.20 }

flush ruleset

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

        # Usar variables
        iif $LAN_IF accept
        iif $WAN_IF ip saddr $TRUSTED_IPS tcp dport $SSH_PORT accept
        tcp dport $WEB_PORTS accept
    }
}

Concatenaciones

# Coincidir combinación de IP y puerto de origen
nft add rule inet filter input ip saddr . tcp sport { 192.168.1.10 . 1234, 192.168.1.20 . 5678 } accept

# Usar en conjunto
nft add set inet filter ssh_access '{ type ipv4_addr . inet_service; }'
nft add element inet filter ssh_access { 192.168.1.10 . 22, 192.168.1.20 . 22 }
nft add rule inet filter input ip saddr . tcp dport @ssh_access accept

Traducción de Direcciones de Red (NAT)

Enmascaramiento (SNAT)

#!/usr/sbin/nft -f

flush ruleset

table inet nat {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;

        # Enmascarar tráfico saliente en interfaz WAN
        oif eth0 masquerade
    }
}

table inet filter {
    chain forward {
        type filter hook forward priority 0; policy drop;

        # Permitir reenvío desde LAN a WAN
        iif eth1 oif eth0 accept

        # Permitir conexiones establecidas de vuelta
        ct state established,related accept
    }
}

Habilitar reenvío IP:

sudo sysctl -w net.ipv4.ip_forward=1
echo "net.ipv4.ip_forward=1" | sudo tee -a /etc/sysctl.conf

NAT de Origen Estático

table inet nat {
    chain postrouting {
        type nat hook postrouting priority 100; policy accept;

        # SNAT tráfico saliente a IP específica
        oif eth0 snat to 203.0.113.50
    }
}

NAT de Destino (Reenvío de Puertos)

table inet nat {
    chain prerouting {
        type nat hook prerouting priority -100; policy accept;

        # Reenviar puerto 80 a servidor interno
        iif eth0 tcp dport 80 dnat to 192.168.1.100:80

        # Reenviar puerto 443 a servidor interno
        iif eth0 tcp dport 443 dnat to 192.168.1.100:443

        # Reenviar SSH en puerto no estándar
        iif eth0 tcp dport 2222 dnat to 192.168.1.10:22
    }
}

table inet filter {
    chain forward {
        type filter hook forward priority 0; policy drop;

        # Permitir conexiones reenviadas
        ct state established,related accept
        iif eth0 oif eth1 tcp dport { 80, 443 } accept
        iif eth0 oif eth1 ip daddr 192.168.1.10 tcp dport 22 accept
    }
}

Balanceo de Carga con NAT

table inet nat {
    chain prerouting {
        type nat hook prerouting priority -100; policy accept;

        # Balanceo de carga round-robin
        tcp dport 80 dnat to numgen inc mod 3 map { \
            0 : 192.168.1.10, \
            1 : 192.168.1.11, \
            2 : 192.168.1.12 \
        }
    }
}

Registro y Monitoreo

Registro Básico

# Registrar paquetes descartados
nft add rule inet filter input limit rate 5/minute log prefix "nftables drop: " drop

# Registrar acceso a servicio específico
nft add rule inet filter input tcp dport 22 log prefix "SSH access: " accept

# Registrar con nivel de log
nft add rule inet filter input log prefix "INPUT: " level info

Registro Avanzado

table inet filter {
    # Cadena de registro
    chain log_and_drop {
        limit rate 5/minute log prefix "nftables denied: " level warning
        drop
    }

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

        # ... reglas de aceptación ...

        # Saltar a cadena de registro para todo lo demás
        jump log_and_drop
    }
}

Monitoreo de Rastreo de Conexión

# Ver tabla conntrack
sudo conntrack -L

# Estadísticas
sudo conntrack -S

# Ver conexiones en tiempo real
sudo conntrack -E

Ver Estadísticas de nftables

# Mostrar contadores de reglas
sudo nft list ruleset -a

# Monitorear cadena específica
watch -n 1 'sudo nft list chain inet filter input'

Endurecimiento de Seguridad

Firewall Endurecido Completo

#!/usr/sbin/nft -f

flush ruleset

table inet filter {
    # Conjuntos para organización
    set allowed_ssh_ips {
        type ipv4_addr
        flags interval
        elements = { 192.168.1.0/24, 10.0.0.100 }
    }

    set blocked_ips {
        type ipv4_addr
        flags interval
    }

    # Cadena de limitación de velocidad
    chain ssh_ratelimit {
        # Permitir 3 conexiones por minuto por IP
        ct state new limit rate over 3/minute drop
        accept
    }

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

        # Loopback
        iif lo accept

        # IPs bloqueadas
        ip saddr @blocked_ips drop

        # Rastreo de conexión
        ct state invalid drop
        ct state established,related accept

        # Anti-spoofing (ajustar para tu red)
        iif eth0 ip saddr { 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 } drop

        # SSH con limitación de velocidad desde IPs confiables
        ip saddr @allowed_ssh_ips tcp dport 22 jump ssh_ratelimit

        # Servicios web
        tcp dport { 80, 443 } ct state new accept

        # Limitación de velocidad ICMP
        ip protocol icmp icmp type echo-request limit rate 1/second accept
        ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate 1/second accept

        # Detección de escaneo de puertos
        tcp flags & (fin|syn|rst|psh|ack|urg) == fin|syn log prefix "Port scan SYN-FIN: " drop
        tcp flags & (fin|syn|rst|psh|ack|urg) == 0 log prefix "Port scan NULL: " drop
        tcp flags & (fin|syn|rst|psh|ack|urg) == fin|psh|urg log prefix "Port scan XMAS: " drop

        # Registrar descartes restantes
        limit rate 5/minute log prefix "nftables input drop: " level warning
    }

    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;
    }
}

Protección DDoS

table inet filter {
    # Protección contra inundación SYN
    chain input {
        type filter hook input priority 0; policy drop;

        # Limitar nuevas conexiones TCP
        tcp flags syn tcp dport { 80, 443 } limit rate over 25/second drop

        # Continuar con otras reglas
        # ...
    }
}

Migración desde iptables

Traducción Automática

# Traducir reglas iptables a nftables
sudo iptables-save > /tmp/iptables.rules
sudo iptables-restore-translate -f /tmp/iptables.rules > /tmp/nftables.nft

# Revisar reglas traducidas
cat /tmp/nftables.nft

# Aplicar si es satisfactorio
sudo nft -f /tmp/nftables.nft

Comparación Lado a Lado

iptables:

iptables -A INPUT -p tcp --dport 22 -j ACCEPT
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
iptables -A INPUT -s 192.168.1.0/24 -j ACCEPT

nftables:

nft add rule inet filter input tcp dport 22 accept
nft add rule inet filter input ct state established,related accept
nft add rule inet filter input ip saddr 192.168.1.0/24 accept

Coexistencia

nftables e iptables pueden coexistir, pero no se recomienda a largo plazo:

# Deshabilitar backend iptables si se usa nftables
sudo systemctl disable iptables
sudo systemctl disable ip6tables

# Habilitar nftables
sudo systemctl enable nftables

Gestión de Configuración

Estructura de Archivo de Configuración

Archivo de configuración principal: /etc/nftables.conf

#!/usr/sbin/nft -f

# Incluir otros archivos
include "/etc/nftables.d/*.nft"

flush ruleset

# Configuración principal
table inet filter {
    # ...
}

Organización modular:

# /etc/nftables.d/00-defines.nft
define WAN_IF = eth0
define LAN_IF = eth1
define SSH_PORT = 22

# /etc/nftables.d/10-filter-table.nft
table inet filter {
    # ...
}

# /etc/nftables.d/20-nat-table.nft
table inet nat {
    # ...
}

Actualizaciones Atómicas de Reglas

# Guardar conjunto de reglas actual
sudo nft list ruleset > /tmp/ruleset-backup.nft

# Probar nueva configuración
sudo nft -c -f /etc/nftables.conf

# Aplicar atómicamente
sudo nft -f /etc/nftables.conf

# Revertir si es necesario
sudo nft -f /tmp/ruleset-backup.nft

Backup y Restauración

#!/bin/bash
# backup-nftables.sh

BACKUP_DIR="/root/nftables-backups"
mkdir -p $BACKUP_DIR

# Guardar conjunto de reglas actual
nft list ruleset > $BACKUP_DIR/nftables-$(date +%Y%m%d-%H%M%S).nft

# Mantener solo últimos 30 días
find $BACKUP_DIR -name "nftables-*.nft" -mtime +30 -delete

echo "Backup de nftables completado"

Resolución de Problemas

Problemas Comunes

Reglas no se cargan:

# Verificar sintaxis
sudo nft -c -f /etc/nftables.conf

# Ver errores detallados
sudo nft -f /etc/nftables.conf 2>&1

Bloqueado por SSH:

# Prevención: Probar con timeout
#!/bin/bash
nft -f /etc/nftables.conf
sleep 60
nft flush ruleset
# Si SSH funciona dentro de 60 segundos, Ctrl+C y guardar permanentemente

Problemas de rendimiento:

# Verificar tamaño de tabla conntrack
cat /proc/sys/net/netfilter/nf_conntrack_count
cat /proc/sys/net/netfilter/nf_conntrack_max

# Aumentar si es necesario
sudo sysctl -w net.netfilter.nf_conntrack_max=262144

Depuración

Habilitar rastreo:

# Agregar regla de rastreo
sudo nft add rule inet filter input tcp dport 80 meta nftrace set 1

# Monitorear rastreo
sudo nft monitor trace

Verificar coincidencia de reglas:

# Ver contadores de reglas
sudo nft list chain inet filter input

# Resetear contadores
sudo nft reset counters inet filter input

Mejores Prácticas

1. Usar Familia inet para Dual-Stack

# En lugar de tablas ip e ip6 separadas
table inet filter {
    # Maneja tanto IPv4 como IPv6
}

2. Organizar con Conjuntos y Mapas

# Mejor que muchas reglas individuales
set web_servers {
    type ipv4_addr
    elements = { 192.168.1.10, 192.168.1.11, 192.168.1.12 }
}

3. Usar Variables para Mantenibilidad

define ADMIN_IPS = { 192.168.1.5, 10.0.0.100 }
define SSH_PORT = 22

# Usar en toda la configuración
ip saddr $ADMIN_IPS tcp dport $SSH_PORT accept

4. Implementar Registro Estratégicamente

# Registrar solo lo necesario, con limitación de velocidad
limit rate 5/minute log prefix "Blocked: "

5. Probar Antes de Producción

# Validar sintaxis
nft -c -f /etc/nftables.conf

# Probar en entorno de staging
# Usar timeout rollback para producción

6. Documentar Tus Reglas

# Usar comentarios
nft add rule inet filter input tcp dport 22 accept comment "SSH access"

# Mantener documentación externa

Conclusión

nftables representa el futuro del filtrado de paquetes en Linux, ofreciendo mejoras significativas sobre iptables en rendimiento, claridad de sintaxis y riqueza de características. Su framework unificado, potentes capacidades de conjuntos y mapas, y actualizaciones atómicas lo hacen ideal para infraestructura moderna que va desde servidores únicos hasta redes empresariales complejas.

Puntos clave:

  • El framework unificado maneja filtrado IPv4, IPv6 y bridge en una herramienta
  • La sintaxis simplificada mejora legibilidad y mantenibilidad
  • Los conjuntos y mapas permiten coincidencia de reglas eficiente y escalable
  • La familia inet simplifica configuraciones dual-stack
  • Las actualizaciones atómicas aseguran aplicación consistente de reglas
  • Mejor rendimiento a través de comunicación optimizada del kernel
  • Las herramientas de migración facilitan la transición desde iptables

A medida que las distribuciones de Linux continúan adoptando nftables como framework de firewall por defecto, dominar sus capacidades se vuelve esencial para administradores de sistemas y profesionales de seguridad. Ya sea desplegando nuevos sistemas o migrando desde iptables, la flexibilidad y poder de nftables proporcionan filtrado de paquetes robusto para requisitos de seguridad de red contemporáneos.

Para escenarios avanzados, explora integración con fail2ban para bloqueo dinámico, automatización con Ansible para despliegue a escala de infraestructura, y la familia netdev de nftables para filtrado ingress de alto rendimiento.