--- title: "Cómo configurar firewalld en Rocky Linux 9 y AlmaLinux 9" description: "Configura firewalld en Rocky Linux 9: zonas, servicios, puertos, reglas enriquecidas y redirección de puertos, probando cada cambio sin perder el acceso SSH." category: "Configuración del Servidor" language: es source: https://cubepath.com/es/docs/configuración-del-servidor/configuracion-de-firewall-con-firewalld-centos-rocky updated: 2026-09-25 --- # Cómo configurar firewalld en Rocky Linux 9 y AlmaLinux 9 firewalld es el gestor de cortafuegos por defecto en Rocky Linux, AlmaLinux, CentOS Stream y RHEL. En lugar de editar reglas de nftables a mano, agrupas interfaces y direcciones de origen en **zonas** y decides qué servicios acepta cada una. En este tutorial configurarás firewalld en Rocky Linux 9 para un servidor web: abrirás los servicios necesarios, restringirás SSH a tus IP de confianza, bloquearás direcciones concretas y redirigirás puertos, todo sin cortarte el acceso. Los comandos son idénticos en AlmaLinux 9, CentOS Stream 9 y RHEL 9, y también funcionan en las versiones 8 y 10. ## Requisitos previos - Un servidor con Rocky Linux 9 o AlmaLinux 9, por ejemplo un VPS de CubePath. - Un usuario no root con privilegios `sudo`. - Acceso a una consola alternativa (consola VNC o de emergencia del proveedor) por si una regla bloquea tu sesión SSH. - La IP pública desde la que te conectas. Puedes consultarla con `curl -4 ifconfig.me` desde tu equipo local. ## Paso 1: Instalar y arrancar firewalld La mayoría de imágenes de Rocky Linux traen firewalld instalado. Si no está, instálalo: ```bash sudo dnf install firewalld ``` Habilítalo para que arranque con el sistema y arráncalo ahora: ```bash sudo systemctl enable --now firewalld ``` Comprueba que está en ejecución: ```bash sudo firewall-cmd --state ``` ```output running ``` > Importante: firewalld permite SSH en la zona `public` por defecto, así que activarlo no corta tu sesión. Si alguien ha modificado esa zona antes, revisa el paso 2 antes de continuar. ## Paso 2: Revisar la zona activa Cada interfaz de red pertenece a una zona, y la zona determina qué tráfico entrante se acepta. Consulta la zona por defecto y las zonas activas: ```bash sudo firewall-cmd --get-default-zone sudo firewall-cmd --get-active-zones ``` ```output public public interfaces: eth0 ``` El nombre de la interfaz puede ser `eth0`, `ens18` u otro según el hipervisor. Muestra toda la configuración de la zona: ```bash sudo firewall-cmd --list-all ``` ```output public (active) target: default icmp-block-inversion: no interfaces: eth0 sources: services: cockpit dhcpv6-client ssh ports: protocols: forward: yes masquerade: no forward-ports: source-ports: icmp-blocks: rich rules: ``` Las zonas predefinidas más útiles son estas: | Zona | Comportamiento por defecto | |---|---| | `drop` | Descarta todo el tráfico entrante sin responder | | `block` | Rechaza el tráfico entrante con un mensaje ICMP | | `public` | Solo acepta los servicios listados. Es la zona por defecto | | `internal` | Pensada para redes internas, admite más servicios | | `trusted` | Acepta todo el tráfico | En todas ellas se permite siempre el tráfico de respuesta a conexiones que inicia el propio servidor. ## Paso 3: Entender la configuración runtime y permanente firewalld mantiene dos configuraciones: - **Runtime**: la que está activa ahora. Se pierde al recargar o reiniciar. - **Permanente**: la guardada en `/etc/firewalld/`. Se aplica al arrancar o al ejecutar `--reload`. Un comando sin `--permanent` solo cambia la configuración runtime. Uno con `--permanent` solo cambia la permanente y no tiene efecto hasta el siguiente `--reload`. Esta separación te da una forma segura de trabajar con reglas arriesgadas: 1. Aplica el cambio sin `--permanent` y comprueba que todo funciona. 2. Guarda el estado actual con `sudo firewall-cmd --runtime-to-permanent`. Si algo sale mal, `sudo firewall-cmd --reload` descarta los cambios runtime y vuelve a la configuración permanente. Para cambios sencillos, como abrir HTTP, es más directo usar `--permanent` y recargar. ## Paso 4: Permitir servicios firewalld incluye definiciones de servicio con sus puertos (están en `/usr/lib/firewalld/services/`). Lista las disponibles: ```bash sudo firewall-cmd --get-services ``` Para un servidor web, permite HTTP y HTTPS de forma permanente y recarga: ```bash sudo firewall-cmd --permanent --add-service=http --add-service=https sudo firewall-cmd --reload ``` ```output success success ``` Si no usas Cockpit (la consola web en el puerto 9090), quita ese servicio de la zona: ```bash sudo firewall-cmd --permanent --remove-service=cockpit sudo firewall-cmd --reload ``` Comprueba los servicios permitidos: ```bash sudo firewall-cmd --list-services ``` ```output dhcpv6-client http https ssh ``` Para ver qué puertos abre un servicio concreto: ```bash sudo firewall-cmd --info-service=https ``` ```output https ports: 443/tcp protocols: source-ports: modules: destination: includes: helpers: ``` ## Paso 5: Abrir puertos concretos Cuando una aplicación no tiene definición de servicio, abre el puerto directamente. Por ejemplo, para una aplicación en el puerto 8080/tcp: ```bash sudo firewall-cmd --permanent --add-port=8080/tcp sudo firewall-cmd --reload ``` También puedes abrir rangos, como los puertos pasivos de un servidor FTP: ```bash sudo firewall-cmd --permanent --add-port=40000-40100/tcp sudo firewall-cmd --reload ``` Verifica los puertos abiertos: ```bash sudo firewall-cmd --list-ports ``` ```output 8080/tcp 40000-40100/tcp ``` Para cerrar un puerto, usa `--remove-port` con el mismo valor. ### Crear un servicio propio Si una aplicación usa varios puertos, es más legible definir un servicio con nombre. Este ejemplo crea `myapp` con los puertos 9000/tcp y 9001/tcp: ```bash sudo firewall-cmd --permanent --new-service=myapp sudo firewall-cmd --permanent --service=myapp --set-description="Mi aplicación" sudo firewall-cmd --permanent --service=myapp --add-port=9000/tcp sudo firewall-cmd --permanent --service=myapp --add-port=9001/tcp sudo firewall-cmd --reload ``` La definición se guarda en `/etc/firewalld/services/myapp.xml`. Ahora puedes añadirla a una zona como cualquier otro servicio: ```bash sudo firewall-cmd --permanent --add-service=myapp sudo firewall-cmd --reload ``` ## Paso 6: Restringir SSH a tus IP de confianza Dejar SSH abierto a todo Internet atrae intentos de fuerza bruta constantes. Una forma limpia de restringirlo es asignar tus IP de confianza a la zona `internal`, que permite SSH, y quitar SSH de la zona `public`. En los comandos siguientes, sustituye `203.0.113.10` por **tu IP pública**. Como este cambio puede bloquear tu acceso, hazlo primero en runtime. Añade tu IP como origen de la zona `internal`: ```bash sudo firewall-cmd --zone=internal --add-source=203.0.113.10/32 ``` Quita SSH de la zona `public`: ```bash sudo firewall-cmd --zone=public --remove-service=ssh ``` Abre una **segunda sesión SSH** desde tu equipo sin cerrar la actual. Si conecta, el cambio funciona y puedes hacerlo permanente: ```bash sudo firewall-cmd --runtime-to-permanent ``` Si la nueva sesión no conecta, ejecuta `sudo firewall-cmd --reload` en la sesión que sigue abierta para deshacer los cambios. Comprueba el resultado: ```bash sudo firewall-cmd --get-active-zones ``` ```output internal sources: 203.0.113.10/32 public interfaces: eth0 ``` El tráfico que llega desde `203.0.113.10` se evalúa con las reglas de `internal`; el resto sigue en `public`, que ya no permite SSH. > Consejo: Si tu IP de casa cambia a menudo, añade también la IP de un bastión o una VPN, o usa la regla con límite de conexiones del paso siguiente en lugar de restringir por origen. ## Paso 7: Usar reglas enriquecidas Las reglas enriquecidas (rich rules) permiten condiciones que no cubren los servicios y puertos simples: origen concreto, registro, límites de frecuencia o rechazo explícito. ### Bloquear una IP o una red Para descartar todo el tráfico de una dirección: ```bash sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="198.51.100.23" drop' sudo firewall-cmd --reload ``` Funciona igual con una red completa, por ejemplo `198.51.100.0/24`. Una alternativa equivalente es asignar el origen a la zona `drop`: ```bash sudo firewall-cmd --permanent --zone=drop --add-source=198.51.100.0/24 sudo firewall-cmd --reload ``` ### Permitir un puerto solo desde una IP Para que solo tu servidor de aplicaciones `10.0.0.5` pueda conectar a MySQL (puerto 3306): ```bash sudo firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="10.0.0.5" port port="3306" protocol="tcp" accept' sudo firewall-cmd --reload ``` No añadas el servicio `mysql` a la zona, o el puerto quedará abierto para todos. ### Limitar la frecuencia de conexiones Esta regla acepta como máximo 10 conexiones nuevas por minuto al servicio SSH. Tiene sentido si mantienes SSH abierto en `public`: ```bash sudo firewall-cmd --permanent --remove-service=ssh sudo firewall-cmd --permanent --add-rich-rule='rule service name="ssh" accept limit value="10/m"' sudo firewall-cmd --reload ``` Primero se quita el servicio `ssh` de la zona, porque si no se aceptaría todo el tráfico SSH antes de llegar a la regla con límite. Las conexiones que superen el límite se rechazan. ### Listar y eliminar reglas enriquecidas ```bash sudo firewall-cmd --list-rich-rules ``` ```output rule family="ipv4" source address="198.51.100.23" drop rule family="ipv4" source address="10.0.0.5" port port="3306" protocol="tcp" accept rule service name="ssh" accept limit value="10/m" ``` Para eliminar una, copia la línea exacta en `--remove-rich-rule`: ```bash sudo firewall-cmd --permanent --remove-rich-rule='rule family="ipv4" source address="198.51.100.23" drop' sudo firewall-cmd --reload ``` ## Paso 8: Redirigir puertos firewalld puede redirigir un puerto entrante a otro puerto local. Esto es útil cuando una aplicación escucha en 8080 y quieres servirla en el 80 sin ejecutarla como root: ```bash sudo firewall-cmd --permanent --add-forward-port=port=80:proto=tcp:toport=8080 sudo firewall-cmd --reload ``` Para redirigir a otra máquina (por ejemplo, `10.0.0.20` en tu red privada), también necesitas activar el enmascaramiento (NAT): ```bash sudo firewall-cmd --permanent --add-masquerade sudo firewall-cmd --permanent --add-forward-port=port=2222:proto=tcp:toport=22:toaddr=10.0.0.20 sudo firewall-cmd --reload ``` Verifica las redirecciones: ```bash sudo firewall-cmd --list-forward-ports ``` ```output port=80:proto=tcp:toport=8080:toaddr= port=2222:proto=tcp:toport=22:toaddr=10.0.0.20 ``` ## Paso 9: Registrar el tráfico rechazado Para diagnosticar qué bloquea el cortafuegos, activa el registro de paquetes denegados: ```bash sudo firewall-cmd --set-log-denied=unicast ``` Este ajuste se guarda automáticamente en la configuración permanente. Los paquetes rechazados aparecen en el registro del kernel: ```bash sudo journalctl -k -g 'REJECT' --since "10 minutes ago" ``` ```output Sep 25 10:12:03 server kernel: filter_IN_public_REJECT: IN=eth0 OUT= SRC=192.0.2.44 DST=203.0.113.50 PROTO=TCP SPT=51544 DPT=3306 ... ``` Cuando termines de diagnosticar, desactívalo para no llenar el diario: ```bash sudo firewall-cmd --set-log-denied=off ``` ## Solución de problemas **Una regla con `--permanent` no tiene efecto.** Los cambios permanentes no se aplican hasta recargar. Ejecuta `sudo firewall-cmd --reload` y comprueba con `--list-all`. **Una regla sin `--permanent` desaparece al reiniciar.** Solo estaba en runtime. Guárdala con `sudo firewall-cmd --runtime-to-permanent`. **Te has quedado sin acceso SSH.** Entra por la consola VNC o de emergencia del proveedor y ejecuta `sudo firewall-cmd --reload` (si el cambio era solo runtime) o revisa la zona con `sudo firewall-cmd --list-all --zone=public` y vuelve a añadir SSH con `sudo firewall-cmd --permanent --add-service=ssh` seguido de `--reload`. **El puerto está abierto pero no responde.** Comprueba que la aplicación escucha en todas las interfaces y no solo en `127.0.0.1` con `sudo ss -tlnp`. Si la aplicación escucha correctamente, revisa SELinux: un puerto no estándar puede necesitar su etiqueta, por ejemplo `sudo semanage port -a -t http_port_t -p tcp 8080` para un servidor web. **Error `ALREADY_ENABLED` o `NOT_ENABLED`.** Es un aviso, no un fallo: la regla ya existía o ya no estaba. La configuración no cambia. ## Conclusión Has configurado firewalld con una zona `public` que solo expone los servicios necesarios, acceso SSH limitado a tus IP de confianza, reglas enriquecidas para casos concretos y redirección de puertos. Trabajar primero en runtime y guardar con `--runtime-to-permanent` te permite probar cualquier cambio sin riesgo de quedarte fuera. Como siguientes pasos, puedes instalar Fail2ban con la acción `firewallcmd-rich-rules` para bloquear IP que fallan el inicio de sesión, cambiar el puerto SSH añadiendo el nuevo puerto a firewalld y a SELinux, o revisar la configuración de SELinux de tu servidor.