Jump to content

# nftables (Español)

From ArchWiki

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-gitAUR.

## 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`

Category:

- Firewalls (Español)

nftables (Español)
Add topic