Configuración del firewall con nftables

En este capítulo se describe la configuración del firewall con nftables. También proporciona ejemplos para configurar tablas, cadenas y reglas nftables que aplican la seguridad de red en un sistema con el comando nft. Estos ejemplos son apropiados para aprender acerca de nftables; sin embargo, para usuarios más avanzados, considere la posibilidad de editar configuraciones nftables desde un archivo. Para obtener más información sobre la sintaxis del archivo nftables, consulte la página del manual nft(8).

Realice lo siguiente:

  • En Oracle Linux 8, este capítulo también describe cómo convertir iptables y ip6tables en la estructura nftables.

  • En el caso de Oracle Linux 9 y Oracle Linux 10, utilice la orientación de conversión en la documentación del firewall específica de la versión.

Nota

Al crear configuraciones nftables mediante comandos nft, estas configuraciones residen en la memoria del sistema hasta que vacíe la memoria o reinicie el sistema. Para que estas configuraciones se mantengan durante los inicios del sistema, considere la posibilidad de exportar las configuraciones a un archivo .nft y configure el sistema para que incluya el archivo al iniciar el servicio nftables. Para obtener más información sobre la exportación de configuraciones a un archivo, consulte Disabling the firewalld Service. Para obtener más información sobre la carga de un archivo de configuración en nftables, ya sea manual o automáticamente, consulte Desactivación del servicio firewalld.

Nota

Cuando se trabaja con nftables, es una buena práctica mantener una conexión local (por ejemplo, con una consola serie si es posible) para recuperarse de errores que podrían bloquearlo del sistema.

Desactivación del servicio firewalld

En Oracle Linux, nftables no está activado por defecto porque el servicio firewalld lo utiliza como backend. Desactive firewalld antes de empezar a trabajar con nftables.

Realice lo siguiente:

  • Para Oracle Linux 8, la salida es similar a:

    firewalld.service
       Loaded: masked (Reason: Unit firewalld.service is masked.)
       Active: inactive (dead)
    
    Jan 20 15:16:07 localhost.localdomain systemd[1]: Starting firewalld - dynamic firewall daemon...
    Jan 20 15:16:08 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon.
    Jan 20 15:16:08 localhost.localdomain firewalld[1635]: WARNING: AllowZoneDrifting is enabled. This is considered an insecure configuration option. It will be removed in a future release. Please consider disabling it now.
    Jan 20 15:52:27 localhost.localdomain systemd[1]: Stopping firewalld - dynamic firewall daemon...
    Jan 20 15:52:27 localhost.localdomain systemd[1]: firewalld.service: Succeeded.
    Jan 20 15:52:27 localhost.localdomain systemd[1]: Stopped firewalld - dynamic firewall daemon.
    
  • Para Oracle Linux 9, la salida es similar a:

    firewalld.service
         Loaded: masked (Reason: Unit firewalld.service is masked.)
         Active: inactive (dead)
    
    Jan 20 15:10:08 localhost.localdomain systemd[1]: Starting firewalld - dynamic firewall daemon...
    Jan 20 15:10:08 localhost.localdomain systemd[1]: Started firewalld - dynamic firewall daemon.
    Jan 20 15:26:25 localhost.localdomain systemd[1]: Stopping firewalld - dynamic firewall daemon...
    Jan 20 15:26:25 localhost.localdomain systemd[1]: firewalld.service: Deactivated successfully.
    Jan 20 15:26:25 localhost.localdomain systemd[1]: Stopped firewalld - dynamic firewall daemon.
    
  • Para Oracle Linux 10, la salida es similar a:

    firewalld.service
         Loaded: masked (Reason: Unit firewalld.service is masked.)
         Active: inactive (dead)
    
    Jan 20 16:05:39 localhost.localdomain systemd[1]: Starting firewalld.service - firewalld - dynamic firewall daemon...
    Jan 20 16:05:40 localhost.localdomain systemd[1]: Started firewalld.service - firewalld - dynamic firewall daemon.
    Jan 20 16:08:33 localhost.localdomain systemd[1]: Stopping firewalld.service - firewalld - dynamic firewall daemon...
    Jan 20 16:08:33 localhost.localdomain systemd[1]: firewalld.service: Deactivated successfully.
    Jan 20 16:08:33 localhost.localdomain systemd[1]: Stopped firewalld.service - firewalld - dynamic firewall daemon.
  1. Jan 20 16:08:33 localhost.localdomain systemd[1]: Stopping firewalld.service - firewalld - dynamic firewall daemon...
      Jan 20 16:08:33 localhost.localdomain systemd[1]: firewalld.service: Deactivated successfully.
      Jan 20 16:08:33 localhost.localdomain systemd[1]: Stopped firewalld.service - firewalld - dynamic firewall daemon.

Acerca de Juegos de Reglas y Tablas

nftables incluye conjuntos de reglas que contienen todas las estructuras de configuración dentro de nftables. Las tablas son la estructura de nivel superior de los juegos de reglas en los que se incluyen varios objetos, como cadenas, reglas, etc.

Gestión de juegos de reglas y tablas

Para gestionar conjuntos de reglas y tablas nftable en la memoria, realice lo siguiente:
  1. Cree una tabla para un tipo de familia de direcciones específico mediante la siguiente sintaxis:

    sudo nft add table <address_family> <table_name>
    En el anterior,
    • <address_family> puede ser ip, ip6, inet, arp, bridge o netdev. Todos los objetos nftables están en una de estas familias de direcciones. Para obtener más información sobre estas familias de direcciones, consulte la página del manual nft(8).
    • <table_name> es el nombre de la tabla. Las tablas contienen cadenas, que a su vez contienen reglas.
    Por ejemplo, el siguiente comando crea una tabla denominada mytable con la familia inet, que incluye direcciones para las versiones IP 4 y 6:
    sudo nft add table inet mytable
  2. Realice lo siguiente:
    • Para ver todos los conjuntos de reglas, haga lo siguiente:
      sudo nft list ruleset
    • Para ver una sola tabla, realice lo siguiente:
      sudo nft list table <address_family> <table_name> 

Acerca de Ganchos y Cadenas

Los ganchos son puntos en un sistema donde los paquetes se pueden interceptar para su procesamiento. Estos enlaces son donde nftables aplica cadenas y reglas que deciden qué sucede con un paquete. Hay diferentes ganchos disponibles dependiendo de la familia de direcciones aplicada a una mesa.

En la siguiente tabla, se muestran los enlaces disponibles para cada familia de direcciones.

Familia de Direcciones

Enlace

Descripción

IP, IPv6, inet/puente

desviar

Procesa todos los paquetes entrantes antes de tomar decisiones de enrutamiento.

entrada

Gestiona los paquetes destinados al sistema local.

hacia delante

Gestiona los paquetes que se reenvían a otro host.

salida

Procesa paquetes que se originan desde el sistema local.

postenrutamiento

Trata con todos los paquetes salientes después del enrutamiento.

entrada

Gestiona los paquetes entrantes antes del reenrutamiento, disponibles en el núcleo 5.10 de Linux para la familia inet.

ARP

entrada

Procesa paquetes para el sistema local.

salida

Gestiona los paquetes enviados desde el sistema local.

Dispositivo de red

entrada

Procesa los paquetes entrantes después de los toques de red, como tcpdump, antes de la manipulación de la capa 3.

salida

Gestiona los paquetes salientes después de la manipulación de la capa 3, pero antes de la salida de red final.

Las cadenas base están unidas a los ganchos. Cuando un paquete llega a un enlace, configurado con una cadena base, el paquete atraviesa la cadena y cada regla de la cadena se evalúa en orden hasta que coincide una regla o se alcanza el final de la cadena. nftables incluye los siguientes tipos de cadena:
  • Cadenas base: son cadenas creadas directamente en un enlace. Por ejemplo, una cadena base denominada myinput puede estar vinculada al enlace de entrada inet para los paquetes IPv4 o IPv6 que llegan al sistema local.
  • Cadenas regulares: son cadenas que saltan de cadenas base u otras cadenas regulares. No se construyen directamente en un gancho, pero pueden ser parte del proceso de toma de decisiones dentro de una cadena base.
Las cadenas base deben incluir el tipo de cadena base, el gancho y los parámetros de prioridad. Los tipos de cadena incluyen:
  • filter: se utiliza principalmente para el filtrado de paquetes, por ejemplo, si se permiten o bloquean paquetes en función de varios criterios, como la IP de origen y destino, los puertos, los protocolos, etc. Este tipo de cadena funciona con todas las familias de direcciones y sus ganchos.
  • nat: se utiliza principalmente para cambiar direcciones IP, puertos o ambos en cabeceras de paquetes para operaciones NAT. Esto incluye cambios en NAT de origen (SNAT) para el tráfico saliente y NAT de destino (DNAT) para el tráfico entrante. Este tipo de cadena se puede configurar con familias de direcciones ip, ipv6 e inet y puede realizar el reenrutamiento, la entrada, la salida y los enganches posteriores al enrutamiento.
  • route: se utiliza principalmente para las decisiones de enrutamiento, como la modificación de una tabla de enrutamiento o el marcado de paquetes para políticas de enrutamiento específicas. Este tipo de cadena se puede utilizar con familias de direcciones ip y ipv6 y solo puede tomar el gancho de salida.

Al utilizar los enlaces de entrada o salida, especifique un nombre de interfaz de red como una cadena con el parámetro device. Cualquier cadena de entrada o salida solo filtra el tráfico de la interfaz especificada en el parámetro del dispositivo.

El parámetro de prioridad utiliza un número entero firmado o un nombre de prioridad estándar para determinar el orden en el que se procesan las cadenas con el mismo enlace. Las cadenas procesan desde valores o nombres de prioridad inferior hasta valores o nombres de prioridad superior.

En la siguiente tabla, se muestran los nombres y valores de prioridad para cada familia de direcciones asociada y tipo de enlace.

Nombre

Valor

Derecho de familia Enlaces

sin procesar

-300

ip, ip6, inet todos

escurridor

-150

ip, ip6, inet todos

dsnat

-100

ip, ip6, inet desviar

filtro

0

ip, ip6, inet, arp, netdev todos

seguridad

50

ip, ip6, inet todos

srcnat

100

ip, ip6, inet postenrutamiento

En la siguiente tabla, se muestran los nombres y valores de prioridad para la familia de direcciones de puente y el tipo de enlace.

Nombre

Valor

Enlaces

dsnat

-300

desviar

filtro

-200

todos

salida

100

salida

srcnat

300

postenrutamiento

También puede definir una política en una cadena que defina si un paquete es accept o drop cuando ninguna de las reglas definidas en la cadena coincide con el paquete. Por defecto, las cadenas base aceptan todos los paquetes. Sin embargo, la definición de una política para eliminar todo el tráfico no permitido explícitamente por una cadena es una buena práctica por motivos de seguridad.

Creación de Cadenas Base

Para crear cadenas base nftable en la memoria, haga lo siguiente:
  1. Cree una cadena para un tipo de familia de direcciones y una tabla específicos con la siguiente sintaxis:

    sudo nft add chain <address_family> <table_name> <chain_name>{ type <chain_type> hook <hook_type> device <network_interface_name> priority <priority> policy <policy> comment <comment> ; }
    
    En el anterior,
    • <address_family> puede ser ip, ip6, inet, arp, bridge o netdev. Todos los objetos nftables están en una de estas familias de direcciones. Para obtener más información sobre estas familias de direcciones, consulte la página del manual nft(8).
    • <table_name> es el nombre de la tabla. Las tablas son contenedores para cadenas, que a su vez son contenedores para reglas.
    • <chain_name> es un nombre arbitrario para la cadena. Las personas que migran desde firewalls basados en iptables a menudo usan la nomenclatura tradicional de iptables.
    • <chain_type> es el tipo de cadena. Los valores válidos para las cadenas base son filter, nat y route. Para obtener más información, consulte About Hooks and Chains.
    • <hook_type> es el tipo de enlace. Los valores posibles dependen de la familia de direcciones y el tipo de cadena seleccionados. Para obtener más información, consulte About Hooks and Chains.
    • <network_interface_name> es el nombre de la interfaz de red para el parámetro de dispositivo. Este parámetro solo es necesario cuando se utilizan los enlaces de entrada o salida.
    • <priority> es el nombre o valor de prioridad de la cadena. La prioridad depende de la familia de direcciones y el tipo de enlace seleccionados. Para obtener más información, consulte About Hooks and Chains.
    • <policy> es la acción realizada si todas las reglas definidas en la cadena no coinciden con el paquete. Los valores válidos son accept o drop. Si no se especifica, el valor por defecto es accept.
    Por ejemplo, el siguiente comando crea una cadena en la tabla mytable denominada mychain con la familia inet. El tipo de cadena es filter, el enlace es input y la prioridad es 0. Por último, la política se define para borrar todos los paquetes que no coinciden con una regla:
    sudo nft add chain inet mytable mychain "{ type filter hook input priority 0 ; policy drop ; }"
  2. Realice lo siguiente:
    • Para ver todas las cadenas, haga lo siguiente:
      sudo nft list chains
    • Para ver una sola cadena, realice lo siguiente:
      sudo nft list chain <address_family> <table_name> <chain_name>

Acerca de las reglas

Puede agregar reglas a las cadenas de una tabla. Las reglas se componen de instrucciones que coinciden con los paquetes en función de varios criterios y aplican acciones como aceptar, borrar, rechazar, etc. Estas instrucciones incluyen elementos como:
  • Juegos, que son recopilaciones de elementos utilizados para la coincidencia.
  • Expresiones, que son bloques de construcción de reglas que definen cómo se confrontan o manipulan los paquetes. Algunos ejemplos incluyen:
    • Coincidencias específicas del protocolo (por ejemplo, ip, ip6, tcp, udp).
    • Coincidencia de direcciones (saddr, daddr).
    • Coincidencia de puertos (sport, dport).
    • La interfaz de red coincide (iifname, oifname).
  • Mapas, que son similares a los conjuntos, pero que pueden asignar un valor a otro. Los mapas se utilizan para escenarios de transformación o coincidencia más complejos.
  • Los mapas de veredicto, que pueden cambiar los veredictos en función del contenido de los paquetes, permiten tomar decisiones de política más dinámicas.
  • Contadores, que realizan un seguimiento del número de paquetes que coinciden con una regla y se muestran al ejecutar un comando list nft que incluye la regla. Los contadores son una forma útil de probar si una regla está funcionando.
  • Cuotas, que limitan la cantidad de datos que se pueden transferir a través de una regla antes de que cambie una acción (por ejemplo, de accept a drop).
  • Flowtables, que permite el reenvío rápido de paquetes de ruta, lo que mejora el rendimiento al omitir el procesamiento regular de paquetes para cierto tráfico.
  • Sentencias, que incluye operaciones como log, reject, jump, goto que cambian el comportamiento de manejo de paquetes.

Las reglas agregadas a una cadena se evalúan de arriba a abajo y de izquierda a derecha.

Para obtener más información sobre la configuración de estas instrucciones, consulte la página del manual nft(8).

Creación de reglas: ejemplos

Esta sección incluye un ejemplo común de reglas creadas dentro de cadenas.

Permitir tráfico local

El siguiente comando crea una regla en mytable dentro de mychain para la familia inet que permite que el tráfico local entre a través de la interfaz de bucle de retorno (iff lo):
sudo nft add rule inet mytable mychain iif lo accept

Permitir tráfico entrante para una conexión existente o relacionada con una conexión existente

Este comando agrega una regla a la cadena mychain de mytable que acepta todo el tráfico entrante que forma parte de una conexión existente o está relacionado con ella:
sudo nft add rule inet mytable mychain ct state established, related accept
En el ejemplo anterior,
  • ct es un asistente de seguimiento de conexiones para IPv4, IPv6 o inet que forma parte del módulo nf_conntrack. Este módulo generalmente se carga de manera predeterminada en la mayoría de los sistemas. Puede mostrar el estado de todas las conexiones al sistema mediante el siguiente comando:
    sudo cat /proc/net/nf_conntrack
    Los posibles estados de conexión son:
    • NEW: el paquete ha iniciado una nueva conexión o está asociado a una conexión que no ha recibido ni enviado paquetes.
    • ESTABLISHED: el paquete está asociado a una conexión que ha recibido y enviado paquetes.
    • RELATED: el paquete está iniciando una nueva conexión, pero está asociado a una conexión existente.
    • INVALID: el paquete está asociado a ninguna conexión conocida.
  • state established, related indica que el comando sólo se aplica a las conexiones con el estado ESTABLISHED o RELATED.
  • accept indica que se puede aceptar cualquier paquete con el estado adecuado.

Esta es una regla común en las configuraciones de firewall para garantizar que las respuestas al tráfico saliente se permitan de nuevo, lo que permite el funcionamiento normal de los servicios de red, como la exploración web, la conectividad SSH, etc., sin necesidad de abrir explícitamente todos los puertos para las conexiones entrantes.

Permitir tráfico SSH entrante

A continuación, se agrega una regla a la cadena mychain de mytable que acepta todo el tráfico TCP entrante en el puerto de destino 22.
sudo nft add rule inet mytable mychain tcp dport 22 accept

Este puerto se utiliza normalmente para el tráfico SSH y asume que el daemon SSH está configurado y en ejecución en el sistema.

Restricción de todo el tráfico IPv4 e IPv6 (botón de aviso grave)

A continuación, se agrega una regla a la tabla mytable que borra todas las direcciones IPv4 e IPv6 entrantes y salientes y actúa como una especie de botón de aviso grave.
sudo nft add rule inet mytable drop

Exportación de configuraciones a un archivo

Para mantener las configuraciones nftable en los inicios o para cambiar de una configuración a otra, puede exportar una nftable en la memoria a un archivo.

Para exportar configuraciones nftable a un archivo, haga lo siguiente:
  1. Enumere los conjuntos de reglas y guarde la salida en un archivo:

    sudo nft list ruleset > /etc/nftables/<export_file_name>.nft

    En el anterior, <nombre_archivo_export> es el nombre del archivo para la información exportada. Este archivo ahora contiene todas las tablas, cadenas y reglas disponibles en la memoria.

  2. Enumere una tabla y guarde la salida en un archivo:

    sudo nft list table <address_family> <table_name> > /etc/nftables/<export_file_name>.nft

    Este archivo ahora contiene una tabla y todas las cadenas y reglas asociadas disponibles en la memoria.

  3. Enumere una cadena y guarde la salida en un archivo:

    sudo nft list chain <address_family> <table_name> <chain_name> > /etc/nftables/<export_file_name>.nft

    Este archivo ahora contiene una cadena en una tabla y todas las reglas asociadas dentro de la cadena disponibles en la memoria.

  4. Asegúrese de que los archivos incluidos en /etc/nftables son ejecutables:
    sudo chmod +x /etc/nftables/<export_file_name>.nft

Carga de configuraciones desde un archivo

Para cargar un juego de reglas, una tabla o una cadena nftable de un archivo en la memoria, puede realizar esta tarea de forma manual o automática al reiniciar un sistema.

Para cargar manualmente un archivo nftables, haga lo siguiente:
  1. Antes de cargar una nueva configuración desde un archivo, borre las tablas existentes:
    sudo nft flush ruleset
    Nota

    Este paso es crucial para evitar conflictos entre las configuraciones nuevas y antiguas y garantiza una aplicación limpia y coherente de las nuevas reglas.
  2. Ejecute el siguiente comando para cargar el archivo en la memoria:

    sudo nft -f /etc/nftables/<import_file_name>.nft
    En el anterior, <nombre_archivo_importación> es el nombre del archivo con la información que se va a importar. Este archivo puede contener un juego de reglas, una o más tablas, una o más cadenas dentro de una tabla y cualquier regla asociada.
    Nota

    La recarga atómica es una función nftables que garantiza que el seguimiento de conexiones se mantenga durante la recarga de reglas, lo que proporciona una transición perfecta a la nueva configuración.
  3. Enumere un conjunto de reglas para verificar que el archivo se haya importado correctamente:

    sudo nft list rulesets
Para cargar automáticamente un conjunto de reglas desde un archivo al reiniciar el sistema, haga lo siguiente:
  1. Edite el archivo /etc/sysconfig/nftables.conf para incluir los archivos de tabla .nft que desea incluir al iniciar. Si no existe, créelo. Por ejemplo, a continuación se muestra que /etc/sysconfig/nftables.conf ahora incluye el archivo /etc/nftables/myruleset.nft exportado.

    # Uncomment the include statement here to load the default config sample
    # in /etc/nftables for nftables service.
    
    include "/etc/nftables/myruleset.nft"
    
    # To customize, either edit the samples in /etc/nftables, append further
    # commands to the end of this file or overwrite it after first service
    # start by calling: 'nft list ruleset >/etc/sysconfig/nftables.conf'.
    
  2. Active e inicie el servicio nftables:

    sudo systemctl enable --now nftables