nftables (Español)

Esta traducción de
Nftables
fue revisada el
2018-09-03
. Si existen
cambios
puede
actualizarla
o avisar al
equipo de traducción
.
Artículos relacionados
iptables
nftables
es un proyecto de netfilter que tiene como objetivo reemplazar el marco existente de tablas{ip,ip6,arp,eb}. Proporciona un nuevo marco de filtrado de paquetes, una nueva utilidad en el espacio de usuario (nft) y una capa de compatibilidad para las tablas{ip,ip6}. Utiliza los hooks existentes, el sistema de seguimiento de la conexiones, los componentes de la línea de espera de los paquetes de red («
packet queues
») del espacio de usuario y el subsistema de registro de netfilter.
Consta de tres componentes principales: una implementación del kernel, la comunicación de la biblioteca libnl con netlink y un frontend de nftables en el espacio de usuario («
nft
») .
El kernel proporciona una interfaz para la configuración del enlace de red («
netlink
»), así como una evaluación del conjunto de reglas en tiempo de ejecución; libnl contiene las funciones de bajo nivel para comunicarse con el kernel, y, por último, el frontend nft proporciona interacción al usuario con nftables.
Para obtener más información también puede visitar la
página oficial de la wiki de nftables
.
Instalación
Instale
las utilidades para el espacio de usuario proporcionadas por el paquete
nftables
o su versión git
nftables-git
AUR
.
Utilización
nftables
hace una distinción entre las reglas temporales realizadas en la línea de órdenes y aquellas otras permanentes cargadas o guardadas en un archivo.
El archivo predeterminado es
/etc/nftables.conf
, que ya contiene una tabla simple de cortafuegos para ipv4/ipv6 llamada «inet filter».
Para utilizarlo,
inicie/active
el servicio
nftables.service
.
Puede consultar el conjunto de reglas con:
# nft list ruleset
Nota
Puede que tenga que crear el archivo
/etc/modules-load.d/nftables.conf
introduciendo por líneas los nombres de todos los módulos relacionados con nftables, para que el servicio de systemd funcione correctamente. Puede obtener una lista de los módulos utilizando esta orden:
$ lsmod | grep '^nf'
De lo contrario, podría obtener el error:
Error: Could not process rule: No such file or directory
.
Configuración
La utilidad de nftable en el espacio de usuario,
nft
, realiza la mayor parte de la evaluación del conjunto de reglas antes de pasarlas al kernel. Las reglas se almacenan en cadenas, que a su vez se almacenan en tablas. Las siguientes secciones indican cómo crear y modificar estos elementos.
Todos los cambios explicados a continuación son temporales. Para que los cambios permanezcan, guarde el conjunto de reglas en el archivo
/etc/nftables.conf
, que será cargado por el servicio
nftables.service
:
# nft list ruleset > /etc/nftables.conf
Nota
nft list
no muestra las definiciones de variables; si tiene alguna en
/etc/nftables.conf
se perderán. Cualquier variable utilizada en las reglas será reemplazada por el valor de esa variable.
Para leer la entrada de un archivo, use el indicador
-f
:
# nft -f
nombre_del_archivo
Tenga en cuenta que las reglas ya cargadas no se ejecutan automáticamente.
Consulte
nft(8)
para obtener una lista completa de todas las órdenes.
Tablas
Las tablas alojan
#Cadenas
. A diferencia de las tablas en iptables, no hay tablas integradas en nftables. La cantidad de tablas y sus nombres depende del usuario. Sin embargo, cada tabla solo tiene una familia de direcciones y solo se aplica a los paquetes de red de esa familia. Las tablas pueden tener una de las cinco familias que se especifican:
Familia de nftables
Utilidad iptables
ip
iptables
ip6
ip6tables
inet
iptables and ip6tables
arp
arptables
bridge
ebtables
ip
(es decir, IPv4) es la familia predeterminada y se usará si no se especifica la familia.
Para crear una regla que se aplique tanto a IPv4 como a IPv6, utilice
inet
.
inet
permite la unificación de las familias
ip
y
ip6
para que las reglas que las defines sean más sencillas para ambas.
Nota
inet
no funciona para las cadenas
nat
, solo para las cadenas
filter
. (
fuente
)
Consulte la sección
ADDRESS FAMILIES
en
nft(8)
para obtener una descripción completa de las familias de direcciones.
En todos los casos,
<
familia
>
es opcional y, si no se especifica, se decanta por
ip
.
Crear una tabla
La siguiente orden añade una nueva tabla:
# nft add table <
familia
> <
tabla
>
Listar las tablas
Para enumerar todas las tablas:
# nft list tables
Listar las cadenas y las reglas de una tabla
Para enumerar todas las cadenas y reglas de una tabla especificada, escriba lo siguiente:
# nft list table <
familia
> <
tabla
>
Por ejemplo, para enumerar todas las reglas de la tabla
filter
de la familia
inet
:
# nft list table inet filter
Borrar una tabla
Para eliminar una tabla, escriba lo siguiente:
# nft delete table <
familia
> <
tabla
>
Las tablas solo se pueden eliminar si no contienen cadenas.
Vaciar una tabla
Para eliminar todas las reglas de una tabla, escriba lo siguiente:
# nft flush table <
familia
> <
tabla
>
Cadenas
El propósito de las cadenas es alojar
#Reglas
. A diferencia de las cadenas en iptables, no hay cadenas integradas en nftables. Esto significa que si ninguna cadena utiliza ningún tipo o hook en el marco de netfilter, los paquetes de red que fluyan a través de esas cadenas no serán tocados por nftables, a diferencia de iptables.
Las cadenas son de dos tipos. Una cadena base que es un punto de entrada para los paquetes de la pila de red, donde se especifica un valor de enlace. Y una cadena normal que puede usarse como un objetivo de salto («
jump
») para una mejor organización.
En todo lo que sigue, la familia es opcional y, si no se especifica, esta se define como ip.
Crear una cadena
Cadena normal
A continuación, agregaremos una cadena normal, llamada
<
cadena
>
, a la tabla denominada
<
tabla
>
:
# nft add chain <
familia
> <
tabla
> <
cadena
>
Por ejemplo, para añadir una cadena normal llamada
tcpchain
, a la tabla
filter
, de la familia de direcciones
inet
, escribiremos lo siguiente:
# nft add chain inet filter tcpchain
Cadena base
Para añadir una cadena base, especificaremos los valores de hook y de priority:
# nft add chain <
familia
> <
tabla
> <
cadena
> { type
tipo
hook
hook
priority
prioridad
\; }
type
puede ser
filter
,
route
, o
nat
.
Para familias de direcciones IPv4/IPv6/Inet el
hook
puede ser
prerouting
,
input
,
forward
,
output
, o
postrouting
. Consulte
nft(8)
para obtener una lista de los hooks para otras familias.
priority
toma un valor entero. Las cadenas con números más bajos se procesan primero y pueden ser negativos.
[1]
Por ejemplo, para añadir una cadena base que filtre los paquetes de entrada:
# nft add chain inet filter input { type filter hook input priority 0\; }
Reemplace
add
con
create
en cualquiera de las órdenes anteriores para añadir una nueva cadena, pero tenga en cuenta que devolvera un error si la cadena ya existe.
Listar las reglas
A continuación enumeraremos todas las reglas de una cadena:
# nft list chain <
familia
> <
tabla
> <
cadena
>
Por ejemplo, la siguiente orden listará las reglas de la cadena llamada
output
, presentes en la tabla
inet
llamada
filter
:
# nft list chain inet filter output
Modificar una cadena
Para modificar una cadena, bastará con llamarla por su nombre y definiremos las reglas que deseamos cambiar.
# nft chain <tabla> <familia> <cadena> { [ type <tipo> hook <hook> device <dispositivo> priority <prioridad> \; policy <política> \; ] }
Si, por ejemplo, solo deseamos cambiar la política de la cadena de entrada («
input
») de la tabla predeterminada, de «accept» a «drop», escribiremos:
# nft chain inet filter input { policy drop \; }
Borrar una cadena
Para eliminar una cadena escribiremos:
# nft delete chain <
familia
> <
tabla
> <
cadena
>
La cadena no debe contener ninguna regla, ni tener un objetivo «jump».
Eliminar las reglas de una cadena
Para eliminar las reglas de una cadena, haremos lo siguiente:
# nft flush chain <
familia
> <
tabla
> <
cadena
>
Reglas
Las reglas se construyen, bien a partir de expresiones («
expressions
») o bien a partir de declaraciones («
statements
»), y están contenidas dentro de cadenas.
Añadir una regla
Sugerencia
La utilidad
iptables-translate
traduce las reglas
iptables
al formato nftables.
Para añadir una regla a una cadena, escribiremos:
# nft add rule <
familia
> <
tabla
> <
cadena
> handle <
identificador
> <
statement
>
La regla se agrega con
handle
, que es opcional. Si no se especifica, la regla se agrega al final de la cadena.
Para anteponer la regla de posición, escriba:
# nft insert rule <
familia
> <
tabla
> <
cadena
> handle <
identificador
> <
statement
>
Si el <
identificador
> (
handle
) no se especifica, la regla se antepone a la cadena.
Expresiones
Por lo general, un
statement
incluye alguna expresión de coincidencia (como «
condición
») y, luego, una «
declaración
» que resuelva (si coinciden). Las declaraciones resolutivas incluyen
accept
,
drop
,
queue
,
continue
,
return
,
<
cadena
> jump
, y
<
cadena
> goto
. Son posibles otros «
statement
» que contengan otras declaraciones resolutivas. Consulte
nft(8)
para obtener más información.
Hay varias expresiones disponibles en nftables y, en su mayor parte, coinciden con sus contrapartes de iptables. La diferencia más notable es que no hay coincidencias genéricas o implícitas. Una coincidencia genérica siempre estuvo disponible, como era el caso de
--protocol
o
--source
. Las coincidencias implícitas eran específicas del protocolo, tales como
--sport
cuando se verificaba que un paquete era TCP.
He aquí es una lista no exhaustiva de las coincidencias disponibles:
meta    (meta propiedades, por ejemplo, interfaces)
icmp    (protocolo ICMP)
icmpv6  (protocolo ICMPv6)
ip      (protocolo IP)
ip6     (protocolo IPv6)
tcp     (protocolo TCP)
udp     (protocolo UDP)
sctp    (protocolo SCTP)
ct      (seguimiento de la conexión)
He aquí una lista no exhaustiva de los argumentos de coincidencia (para una lista más completa, vea
nft(8)
):
meta:
  oif <INDICE de la interfaz de salida>
  iif <INDICE de la interfaz de entrada>
  oifname <NOMBRE de la interfaz de salida>
  iifname <NOMBRE de la interfaz de entrada>

  (oif y iif aceptan argumentos de cadena y se convierten en índices de interfaz)
  (oifname y iifname son más dinámicos, pero más lentos debido a la coincidencia de cadenas)

icmp:
  type <tipo icmp>

icmpv6:
  type <tipo icmpv6>

ip:
  protocol <protocolo>
  daddr <dirección de destino>
  saddr <dirección de origen>

ip6:
  daddr <dirección de destino>
  saddr <dirección de origen>

tcp:
  dport <puerto de destino>
  sport <puerto de origen>

udp:
  dport <puerto de destino>
  sport <puerto de origen>

sctp:
  dport <puerto de destino>
  sport <puerto de origen>

ct:
  state <new | established | related | invalid>
Nota
nft
no utiliza
/etc/services
para hacer coincidir los números de los puertos con los nombres, en su lugar utiliza una
lista interna
. Para mostrar las asignaciones de puertos desde la línea de órdenes, utilice, por ejemplo
nft describe tcp dport
.
Eliminación
Las reglas individuales solo se pueden eliminar mediante sus identificadores («
handle
»). La orden
nft --handle list
se puede usar para determinar los identificadores de las reglas. Advierta que el modificador
--handle
le dice a
nft
que liste los identificadores en la salida.
Las siguientes órdenes determinan, primero, el identificador de una regla y, luego, borra dicha regla. El argumento
--number
es útil para que vuelque algún resultado numérico, como las direcciones IP no resueltas.
# nft --handle --numeric list chain filter input
table ip fltrTable {
     chain input {
          type filter hook input priority 0;
          ip saddr 127.0.0.1 accept # handle 10
     }
}
# nft delete rule fltrTable input handle 10
Todas las cadenas en una tabla se pueden limpiar con la orden
nft flush table
. Las cadenas individuales pueden eliminarse utilizando las órdenes
nft flush chain
o
nft delete rule
.
# nft flush table foo
# nft flush chain foo bar
# nft delete rule ip6 foo bar
La primera orden, limpia todas las cadenas en la tabla ip
foo
. La segunda, limpia la cadena
bar
en la tabla ip
foo
. La tercera, borra todas las reglas en la cadena
bar
en la tabla ip6
foo
.
Recargar todo
Vacíe el conjunto de reglas actuales:
# echo "flush ruleset" > /tmp/nftables
Vuelque el conjunto de reglas actuales:
# nft list ruleset >> /tmp/nftables
Ahora puede editar /tmp/nftables y aplicar los cambios con:
# nft -f /tmp/nftables
Ejemplos
Estación de trabajo
/etc/nftables.conf
flush ruleset

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

                # aceptar cualquier tráfico de localhost
                iif lo accept

                # aceptar tráfico originado por nosotros
                ct state established,related accept

		# aceptar ICMP y IGMP
		ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept
		ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept
		ip protocol igmp accept

                # descomentar la siguiente línea para aceptar servicios locales comunes
                #tcp dport { 22, 80, 443 } ct state new accept

                # cuenta y descarta cualquier otro tráfico
                counter drop
        }
}
Cortafuegos simple con IPv4/IPv6
cortafuegos.rules
# A simple cortafuegos

flush ruleset

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

		# conexiones establecidas/relacionadas
		ct state established,related accept

		# conexiones no válidas
		ct state invalid drop

		# interfaz loopback
		iif lo accept

		# ICMP y IGMP
		ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept
		ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept
		ip protocol igmp accept

		# SSH (puerto 22)
		tcp dport ssh accept

		# HTTP (puertos 80 y 443)
		tcp dport { http, https } accept
	}

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

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

}
Tipo de límite del cortafuegos IPv4/IPv6
cortafuegos.2.rules
table inet filter {
	chain input {
		type filter hook input priority 0; policy drop;

		ct state invalid drop

		iif lo accept

		# sin saturación de ping:
		ip protocol icmp icmp type echo-request limit rate over 10/second burst 4 packets  drop
		ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 10/second burst 4 packets drop

		ct state established,related accept

		# ICMP y IGMP
		ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, packet-too-big, time-exceeded, parameter-problem, mld-listener-query, mld-listener-report, mld-listener-reduction, nd-router-solicit, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert, ind-neighbor-solicit, ind-neighbor-advert, mld2-listener-report } accept
		ip protocol icmp icmp type { destination-unreachable, router-solicitation, router-advertisement, time-exceeded, parameter-problem } accept
		ip protocol igmp accept

		# evitar la fuerza bruta en ssh:
		tcp dport ssh ct state new limit rate 15/minute accept

	}

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

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

}
Jump
Al usar saltos (jump) en el archivo de configuración, primero es necesario definir la cadena
target
. De lo contrario, nos podríamos encontrar con el error
Error: Could not process rule: No such file or directory
.
jump.rules
table inet filter {
    chain web {
        tcp dport http accept
        tcp dport 8080 accept
    }
    chain input {
        type filter hook input priority 0;
        ip saddr 10.0.2.0/24 jump web
        drop
    }
}
Diferentes reglas para diferentes interfaces
Si su equipo tiene más de una interfaz de red y le gustaría usar diferentes reglas para las diferentes interfaces, puede usar una cadena de filtros «
dispatching
», y luego cadenas de filtros específicas para cada interfaz. Por ejemplo, supongamos que tiene un equipo que actúa como un enrutador doméstico, y desea ejecutar un servidor web accesible a través de la LAN (interfaz nsp3s0), pero no desde Internet público (interfaz enp2s0), es posible que desee considerar una estructura como esta:
table inet filter {
  chain input { # esta cadena sirve como despachador
    type filter hook input priority 0;

    iif lo accept # always accept loopback
    iifname enp2s0 jump input_enp2s0
    iifname enp3s0 jump input_enp3s0

    reject with icmp type port-unreachable # refuse traffic from all other interfaces
  }
  chain input_enp2s0 { # reglas aplicables a la interfaz de acceso pública
    ct state {established,related} accept
    ct state invalid drop
    udp dport bootpc accept
    tcp dport bootpc accept
    reject with icmp type port-unreachable # todo el tráfico restante
  }
  chain input_enp3s0 {
    ct state {established,related} accept
    ct state invalid drop
    udp dport bootpc accept
    tcp dport bootpc accept
    tcp port http accept
    tcp port https accept
    reject with icmp type port-unreachable # todo el tráfico restante
  }
  chain ouput { # dejamos que todo salga
    type filter hook output priority 0;
    accept
  }
 }
De forma alternativa, podría elegir solo una declaración
iifname
, a modo de interfaz única ascendente, y colocar las reglas predeterminadas para todas las demás interfaces en un solo lugar, en vez de enviarlas para cada interfaz.
Enmascaramiento
nftables tiene una palabra clave especial
masquerade
«donde la dirección de origen se configura automáticamente hacia la dirección de la interfaz de salida» (
source
). Esto es particularmente útil para situaciones en las que la dirección IP de la interfaz es impredecible o inestable, como la interfaz de los enrutadores que se conectan a muchos ISP. Sin esta opción, las reglas de traducción de las direcciones de red tendrían que actualizarse cada vez que cambiara la dirección IP de la interfaz.
Para usarlo:
asegúrese de que el enmascaramiento esté activado en el kernel (
true
(verdadero) si se utiliza el kernel predeterminado); de lo contrario, durante la configuración del kernel, defínalo:
CONFIG_NFT_MASQ=m
la palabra clave
masquerade
solo se puede usar en cadenas de tipo
nat
, las cuales no se pueden combinar en una tabla con la familia
inet
. Utilice una tabla con la familia
ip
y/o
ip6
en su lugar.
el enmascaramiento es un tipo de fuente NAT, por lo que solo funciona en la ruta de salida.
Ejemplo para un equipo con dos interfaces: LAN conectada a
nsp3s0
, e Internet pública conectada a
enp2s0
:
table ip nat {
  chain prerouting {
    type nat hook prerouting priority 0;
  }
  chain postrouting {
    type nat hook postrouting priority 0;
    oifname "enp0s2" masquerade
  }
}
Consejos y trucos
Cortafuegos stateful simple
Consulte
Simple stateful firewall (Español)
para obtener más información.
Proteger un único equipo
Vacíe el conjunto de reglas actuales:
# nft flush ruleset
Añada una tabla:
# nft add table inet filter
Añada las cadenas base: input, forward y output. La política de
input
y
forward
será
drop
. La política de
output
será
accept
.
# nft add chain inet filter input { type filter hook input priority 0 \; policy drop \; }
# nft add chain inet filter forward { type filter hook forward priority 0 \; policy drop \; }
# nft add chain inet filter output { type filter hook output priority 0 \; policy accept \; }
Añada dos cadenas normales que se asociarán con tcp y udp:
# nft add chain inet filter TCP
# nft add chain inet filter UDP
El tráfico relacionado («
related
») y el ya establecido («
established
») será aceptado («
accept
»):
# nft add rule inet filter input ct state related,established accept
Se aceptará todo el tráfico procedente de la interfaz loopback:
# nft add rule inet filter input iif lo accept
Se establecerá la política de descartar («
drop
») para cualquier tráfico no válido:
# nft add rule inet filter input ct state invalid drop
Se aceptarán nuevas solicitudes de echo (pings):
# nft add rule inet filter input ip protocol icmp icmp type echo-request ct state new accept
El nuevo tráfico upd saltará («
jump
») a la cadena UDP:
# nft add rule inet filter input ip protocol udp ct state new jump UDP
El nuevo tráfico tcp saltará («
jump
») a la cadena TCP:
# nft add rule inet filter input ip protocol tcp tcp flags \& \(fin\|syn\|rst\|ack\) == syn ct state new jump TCP
Se rechazará («
reject
») todo el tráfico no procesado por la restantes reglas:
# nft add rule inet filter input ip protocol udp reject
# nft add rule inet filter input ip protocol tcp reject with tcp reset
# nft add rule inet filter input counter reject with icmp type prot-unreachable
En este punto, debe decidir qué puertos desea abrir para las conexiones entrantes, que son manejadas por las cadenas TCP y UDP. Por ejemplo, para abrir conexiones para un servidor web, añada:
# nft add rule inet filter TCP tcp dport 80 accept
Para aceptar conexiones HTTPS de un servidor web en el puerto 443:
# nft add rule inet filter TCP tcp dport 443 accept
Para aceptar el tráfico SSH en el puerto 22:
# nft add rule inet filter TCP tcp dport 22 accept
Para aceptar solicitudes de DNS entrantes:
# nft add rule inet filter TCP tcp dport 53 accept
# nft add rule inet filter UDP udp dport 53 accept
Asegúrese de hacer que sus cambios permanezcan cuando esté satisfecho.
Evitar ataques de fuerza bruta
Sshguard
es un programa que puede detectar ataques de fuerza bruta y modificar el cortafuegos en función de las direcciones IP temporalmente bloqueadas. Consulte
Sshguard#nftables
sobre cómo configurar nftables para usarlo con Sshguard.
Véase también
netfilter nftables wiki
debian:nftables
gentoo:nftables
First release of nftables
nftables quick howto
The return of nftables
What comes after ‘iptables’? Its successor, of course: `nftables`