footer-logofooter-logo
iptables vs nftables: qué ha cambiado y cómo migrarVolver

iptables vs nftables: qué ha cambiado y cómo migrar

Si tu servidor ejecuta una distro Debian, Ubuntu o de la familia RHEL actual, tus reglas de «iptables» casi con toda seguridad ya se ejecutan dentro de nftables. El comando iptables es un shim de compatibilidad desde 2019. La verdadera pregunta no es cuál gana; es si vas a seguir escribiendo reglas en una sintaxis legacy encima del nuevo motor. Esta guía cubre lo que realmente cambió a nivel arquitectónico, una comparación de sintaxis lado a lado, lo que dicen honestamente los datos de rendimiento, y una ruta de migración que no rompe Docker ni te deja fuera.

22 de julio de 2026

por Jesse Schokker

nftables

iptables

Firewall

Linux

Loading...

La respuesta antes que nada: probablemente ya estés ejecutando nftables

El planteamiento «iptables vs nftables» sugiere una elección entre dos opciones vivas. En la mayoría de los servidores, esa elección ya la había tomado tu distribución en 2026:

  • En Debian 10+ y Ubuntu 20.10+, el comando iptables es por defecto iptables-nft, una capa de compatibilidad que acepta la sintaxis de iptables pero programa el subsistema nf_tables del kernel. Tus reglas de iptables ya corren sobre el motor nftables.
  • En la familia RHEL (RHEL/AlmaLinux/Rocky 9 y 10), todo el framework de iptables está deprecado, firewalld habla nftables de forma nativa, y RHEL 10 ya no incluye en absoluto el módulo de kernel legacy ip_tables.
  • En upstream, iptables está en modo mantenimiento: sigue recibiendo versiones (1.8.13 llegó en marzo de 2026), pero todo el desarrollo de funcionalidades ocurre en nftables.

Así que el consejo práctico es breve: los conjuntos de reglas de iptables existentes y funcionales no son una emergencia; la capa de compatibilidad es buena y estable. Pero las reglas nuevas y la automatización nueva deberían escribirse en nftables nativo: una sola sintaxis para IPv4 e IPv6, sets y maps que escalan, recargas atómicas, y ninguna dependencia de un shim cuyo tooling subyacente las distros ya han marcado para una eventual eliminación. El resto de este artículo son los detalles detrás de ese consejo, más la mecánica de migración.

Cómo llegamos hasta aquí

netfilter, el subsistema de filtrado de paquetes del kernel, ha pasado por tres generaciones visibles para el usuario: ipchains (kernel 2.2), iptables (kernel 2.4, 2001) y nftables (integrado en el kernel 3.13, 2014). nftables fue escrito por el mismo equipo de netfilter para arreglar los problemas estructurales de iptables en lugar de parchearlos por fuera.

La versión clave fue iptables 1.8 (2018), que dividió el comando en dos variantes: iptables-legacy (la implementación clásica) y iptables-nft (misma sintaxis de línea de comandos, pero las reglas las ejecuta el motor de kernel nf_tables). Las distros cambiaron su alias por defecto a la variante nft casi de inmediato, y así fue como millones de servidores migraron de motor sin que sus administradores se dieran cuenta:

DistroEstado
Debian 10 → 13iptables = iptables-nft por defecto desde 2019; nftables es el framework recomendado
Ubuntu 20.10 → 26.04 LTSIgual: iptables-nft por defecto; ufw sigue dirigiendo la sintaxis de iptables (sobre el shim)
RHEL 8firewalld gana un backend nftables; iptables presente
RHEL/Alma/Rocky 9Framework de iptables entero deprecado; firewalld/nftables es la vía soportada
RHEL/Alma/Rocky 10 (2025)Módulo de kernel legacy ip_tables eliminado; el userspace de iptables-nft se sigue distribuyendo, deprecado

Comprueba qué está usando realmente una máquina dada; la respuesta se imprime entre paréntesis:

$ iptables -V
iptables v1.8.10 (nf_tables)   # ← the shim, executing on nftables
iptables v1.8.10 (legacy)      # ← the classic engine

Qué cambió realmente

Las diferencias que importan en el día a día operativo, no la lista de marketing:

Una sola herramienta, las dos familias de direcciones

El pecado original de iptables: iptables, ip6tables, arptables y ebtables eran cuatro herramientas separadas con cuatro conjuntos de reglas separados, y cada servidor dual-stack necesitaba su política escrita (y mantenida, y auditada) dos veces. Olvidar la mitad de IPv6 era el agujero clásico. La familia inet de nftables aplica una sola tabla tanto a IPv4 como a IPv6. Toda la clase de bugs de «v4 protegido, v6 olvidado» desaparece estructuralmente.

Los sets y los maps son de primera clase

En iptables, comparar 500 direcciones significaba 500 reglas (evaluadas linealmente), o acoplar la herramienta separada ipset. En nftables, los sets son nativos:

nft add set inet filter blocklist '{ type ipv4_addr; flags interval; }'
nft add element inet filter blocklist '{ 203.0.113.0/24, 198.51.100.7 }'
nft add rule inet filter input ip saddr @blocklist drop

Una sola regla, una búsqueda casi O(1), actualizable en tiempo de ejecución sin tocar el conjunto de reglas. Los maps van más allá, y asocian criterios de coincidencia con acciones o destinos (construcciones al estilo de dnat to tcp dport map { 80 : 10.0.0.10, 443 : 10.0.0.11 } comprimen familias enteras de reglas en una sola búsqueda). Los sets dinámicos también impulsan la limitación de tasa por origen, que usamos en nuestra base de reglas de firewall por defecto.

Reemplazo atómico del conjunto de reglas

nft -f ruleset.conf valida y aplica el archivo completo de forma atómica: o carga por completo, o el conjunto de reglas antiguo permanece intacto. Los scripts de iptables aplicaban las reglas de un comando en un comando, así que un fallo a mitad de camino dejaba el firewall en un estado a medio configurar (de vez en cuando, de forma memorable, en el estado en el que el drop por defecto ya se había aplicado pero el allow de SSH todavía no). iptables-restore mitigaba esto por tabla; en nftables, ese es el único modo de funcionamiento. Además, nft -c te da una comprobación de sintaxis en modo dry-run.

Sin chains integradas, sin pipeline fija

iptables le daba a cada tabla chains fijas (INPUT, FORWARD, OUTPUT...) que existen se usen o no, cada una imponiendo un coste por paquete. En nftables, solo creas las chains que necesitas y las conectas a hooks del kernel con prioridades explícitas. El overhead de un firewall vacío es literalmente cero, y el conjunto de reglas que lees es toda la verdad, nada implícito.

Mejor introspección y automatización

nft monitor transmite los cambios del conjunto de reglas en directo (excelente para depurar el «¿qué acaba de cambiar mi firewall?»), los counters son opt-in por regla, y nft -j habla JSON en los dos sentidos, la respuesta moderna a toda una generación de parsers frágiles de iptables-save. Si generas la configuración del firewall con plantillas de Ansible o Terraform, nftables nativo es notablemente menos doloroso.

Sintaxis lado a lado

Las tareas que realmente haces, en los dos lenguajes:

Tareaiptablesnftables
Listar reglasiptables -L -n -vnft list ruleset
Permitir un puertoiptables -A INPUT -p tcp --dport 443 -j ACCEPTnft add rule inet filter input tcp dport 443 accept
Varios puertos-m multiport --dports 80,443,8443tcp dport { 80, 443, 8443 } accept
Aceptar stateful-m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPTct state established,related accept
v4 y v6 a la vezejecutar iptables y ip6tablesuna sola tabla inet cubre ambas
Coincidir con muchas IPipset create + -m set --match-setset nativo: ip saddr @blocklist drop
Registrar y luego descartardos reglas (-j LOG, luego -j DROP)una regla: log prefix "drop: " drop
Limitación de tasa-m limit --limit 10/minutelimit rate 10/minute
Guardar / restaurariptables-save / iptables-restore (por familia)nft list ruleset > f / nft -f f (atómico, ambas familias)
Comprobación en dry-runn/anft -c -f ruleset.conf

La columna de nftables se lee como un lenguaje en vez de como la sopa de flags de un comando, porque lo es: las expresiones se combinan libremente (ip saddr @admins tcp dport 22 ct state new accept) en lugar de requerir un módulo de coincidencia a medida por cada función.

Rendimiento: la versión honesta

Las afirmaciones de que nftables es mucho más rápido (o más lento) son fáciles de encontrar y, en su mayoría, infundadas. Los datos públicos creíbles:

  • Los desarrolladores de netfilter de Red Hat compararon ambos en 2017: con conjuntos de reglas pequeños y lineales, iptables era en realidad algo más rápido; el panorama se invierte en cuanto entran los sets: al comparar en ~120+ puertos o grandes grupos de direcciones, iptables se degrada linealmente mientras que nftables se mantiene plano. Su conclusión fue que las arquitecturas son comparables y que la ventaja está en los sets/maps, no en la velocidad bruta por regla. (datos de 2017: la forma de la conclusión se ha mantenido, pero trata las cifras absolutas como históricas.)
  • A escala de orquestación la diferencia se vuelve visible: el kube-proxy de Kubernetes ganó un modo nftables GA en la 1.33, sobre todo porque la evaluación lineal de reglas y las recargas completas de tabla de iptables duelen en decenas de miles de servicios. Con ~30,000 servicios, la latencia de cola del modo nftables superó a la mejor latencia del modo iptables. Cabe destacar que el modo iptables sigue siendo el predeterminado de Kubernetes por compatibilidad.

En un único servidor con docenas de reglas, no vas a medir ninguna diferencia. Elige nftables por la expresividad, la atomicidad y el hecho de que ahí es donde va ahora todo el esfuerzo de mantenimiento y desarrollo, no por el throughput.

Migrar

Paso 1: averigua qué estás usando

iptables -V (ver más arriba). Comprueba también si hay reglas en ambos motores, un lío sorprendentemente común después de migraciones parciales:

iptables-legacy -L -n 2>/dev/null   # anything here runs on the old engine
nft list ruleset                    # the full truth, including iptables-nft rules

nft list ruleset muestra todo lo que hay en nf_tables, incluidas las reglas creadas a través del shim; es el único comando que nunca te miente sobre el estado real del firewall.

Paso 2: traducción mecánica

El paquete de iptables incluye traductores. Misma sintaxis de entrada, sintaxis nft de salida:

$ iptables-translate -A INPUT -p tcp --dport 22 -m conntrack --ctstate NEW -j ACCEPT
nft 'add rule ip filter INPUT tcp dport 22 ct state new counter accept'

# whole ruleset at once:
iptables-save > current.rules
iptables-restore-translate -f current.rules > ruleset.nft
nft -c -f ruleset.nft   # syntax-check before applying

(ip6tables-restore-translate para la mitad de v6.) La salida es correcta pero literal: reproduce tal cual tu duplicación v4/v6 y tu estructura por regla.

Paso 3: adoptar de verdad el modelo

Trata el archivo traducido como un andamiaje, y luego reestructura: fusiona los conjuntos de reglas v4/v6 en una sola tabla inet, comprime las reglas repetidas de puerto/dirección en sets, y añade comentarios. Un conjunto de reglas de iptables de 100 líneas se convierte habitualmente en 30 líneas legibles de nftables. Nuestro artículo de referencia de firewall es un esqueleto razonable sobre el que migrar. Aplícalo con un rollback programado y una segunda sesión SSH abierta (la mecánica para evitar quedarte fuera también se cubre allí).

Las trampas

  • No ejecutes reglas en los dos motores. Las reglas de iptables legacy y las de nftables se evalúan ambas, de forma independiente. Un paquete tiene que sobrevivir a las dos. Esto «funciona» hasta que produce un comportamiento imposible de depurar. Migra, verifica, y luego vacía el lado legacy.
  • Docker sigue hablando iptables. Docker programa su NAT/forwarding por defecto a través de la interfaz de iptables (sin problema: en sistemas modernos eso es el shim de nft; no elimines el paquete iptables en un host Docker). Su backend nativo de nftables salió de forma experimental en Engine 29, pero es opt-in. Consecuencia práctica: en un host Docker, pon tu política en la chain DOCKER-USER o en tus propias tablas, y no hagas flush ruleset a ciegas. Eso elimina también las reglas de Docker. (La misma historia para los nodos de Kubernetes: comprueba tu CNI y tu modo de kube-proxy antes de tocar el firewall.)
  • Los frontends están bien. Elige una sola capa. ufw (sintaxis de iptables sobre el shim) y firewalld (backend nativo de nftables desde 2018) funcionan hoy correctamente los dos. El antipatrón es editar las tablas de nft a mano en una máquina gestionada por un frontend; el frontend ganará en la siguiente recarga.

Cuándo tiene sentido quedarse en iptables

Honestidad sobre el otro lado: un servidor estable, tipo appliance, con un conjunto de reglas iptables-nft que funciona y está auditado, y sin desarrollo activo de reglas, tiene poco que ganar con una reescritura. Un tooling que solo genera iptables (acciones antiguas de fail2ban, orquestación legacy) es también una razón legítima para posponerlo; el shim existe precisamente para esto. La línea que hay que mantener es direccional: no escribas sistemas, roles o documentación nuevos contra la sintaxis legacy, porque la familia RHEL ya ha programado su eliminación y el resto del ecosistema sigue al equipo de netfilter de Red Hat.

Preguntas frecuentes

¿Está iptables deprecado?

Con precisión: deprecado por las distribuciones, mantenido en upstream. El proyecto netfilter sigue publicando versiones de iptables (1.8.13, marzo de 2026) y no ha anunciado ningún fin de vida. Pero Red Hat deprecó todo el framework de iptables en RHEL 9, eliminó el módulo de kernel legacy en RHEL 10, y en todas las distros grandes el motor por defecto lleva años siendo nftables. «Muerto» es incorrecto; «interfaz legacy con los días contados» es correcto.

¿Usan ufw y firewalld nftables?

firewalld: sí, de forma nativa. nftables es su backend por defecto desde 2018. ufw: de forma indirecta. Genera reglas iptables y las ejecuta a través del binario iptables del sistema, que en cualquier Ubuntu moderno es el shim basado en nft, así que las reglas acaban en nf_tables; ufw en sí no tiene modo nftables nativo. En cualquier caso, tus reglas terminan en el mismo subsistema del kernel.

¿Dejarán de funcionar mis reglas de iptables si cambio?

La lógica de tus reglas se traduce de forma limpia; iptables-restore-translate convierte un conjunto de reglas guardado de forma mecánica, y el motor nftables admite todo lo que hace el conjunto de funciones básico de iptables. Lo que no se traslada automáticamente: las definiciones de ipset (recrearlas como sets nativos), cualquier script que analice la salida de iptables -L, y las suposiciones sobre chains integradas. Traduce, haz un dry-run con nft -c, aplica de forma atómica, mantén un rollback programado.

¿Es nftables más rápido que iptables?

A pequeña escala, no. Los propios benchmarks de Red Hat mostraron que los conjuntos de reglas lineales simples favorecían ligeramente a iptables. nftables gana donde la estructura importa: sets grandes de puertos/direcciones (búsqueda plana en vez de lineal), conjuntos de reglas muy grandes, y cambios de reglas frecuentes (actualizaciones incrementales atómicas en vez de recargas completas de tabla, la razón por la que Kubernetes construyó un kube-proxy con nftables). Para un firewall de servidor típico, elige según la mantenibilidad; en rendimiento están empatados.

Desplegar en Serverside

Escribas la sintaxis que escribas, el firewall del host es una de las dos capas de nuestra red: cada servidor dedicado incluye un firewall perimetral en autoservicio (el tráfico no asociado a un servicio se descarta aguas arriba antes de llegar a tu puerto), más mitigación DDoS siempre activa en el ASN 55285, con aprovisionamiento en menos de un minuto en cualquier distribución Linux importante.

Sigue construyendo sobre este artículo con el conjunto de reglas de firewall por defecto para un servidor Linux completo, el panorama de amenazas más amplio en ataques DDoS explicados, y análisis forense de tráfico práctico en capturar y analizar un ataque DDoS con Wireshark.

Jesse Schokker

Escrito por

Jesse Schokker

Co-founder & CTO, Serverside.com

Jesse is the co-founder and CTO of Serverside.com, where he leads the engineering behind the company's bare-metal cloud: from the ASN 55285 backbone to the core automation that drives day-to-day operation. He writes about dedicated servers, operating systems, and running production workloads on bare metal.