SSD Nodes Learn Hosting plans →
Guías Matt ConnorPor Matt Connor · Actualizado 2026-09-04

Cambiar el puerto SSH con SELinux y firewalld

Aprende a mover sshd en Rocky Linux, AlmaLinux, CentOS Stream o Fedora: configura firewalld, etiqueta SELinux y sshd_config sin perder la sesión.

Por qué cambiar el puerto SSH requiere tres pasos

Para cambiar el puerto SSH en Rocky Linux, AlmaLinux, CentOS Stream o Fedora, una sola edición no es suficiente. Tres sistemas independientes determinan si funciona una conexión en el puerto nuevo. firewalld decide si el paquete llega a la máquina. SELinux decide si sshd tiene permitido asociarse a ese número de puerto. sshd_config decide qué puerto solicita el daemon. Si omite el paso de SELinux, el daemon no se inicia. Si omite el paso de firewalld, se inicia y escucha, pero nadie puede acceder a él.

En Ubuntu, el mismo trabajo requiere una edición y un reinicio, porque Ubuntu usa AppArmor en lugar de SELinux y no incluye ningún perfil que restrinja los puertos a los que sshd puede asociarse. Si ufw está activo, debe añadir una regla. Esa es toda la diferencia. La familia RHEL incluye firewalld activo y SELinux en modo enforcing en una instalación nueva, y ambos tienen en cuenta los números de puerto.

Realice el trabajo en este orden para que la sesión actual siga activa durante todos los pasos:

  1. Abra el puerto nuevo en firewalld y mantenga abierto el puerto 22 por ahora.
  2. Añada la etiqueta de SELinux para el puerto nuevo con semanage.
  3. Establezca el puerto en la configuración de sshd.
  4. Reinicie sshd y, después, inicie sesión en el puerto nuevo desde una segunda terminal antes de cerrar la primera.
Busque la consola web de su proveedor (VNC o serie) antes de empezar y compruebe que puede iniciar sesión mediante ella. Esa consola le permite recuperar el acceso si el cambio falla. Cambiar un puerto es uno de los motivos más frecuentes por los que un usuario se queda sin acceso a un servidor que acaba de contratar.

Primero, instale semanage

semanage es la herramienta que edita la configuración de políticas de SELinux, y una instalación mínima de Rocky Linux o AlmaLinux no la incluye. Se encuentra en policycoreutils-python-utils.

sudo dnf install -y policycoreutils-python-utils

Ejecutar el comando antes de instalar ese paquete muestra sudo: semanage: command not found. En este punto, muchos lectores concluyen que SELinux no está instalado y omiten el paso. SELinux sí está instalado. Sólo falta la herramienta de administración. Si la sintaxis de dnf es nueva para usted, las equivalencias de comandos de dnf y apt la relacionan con lo que ya conoce.

Elija un puerto y compruebe que ningún proceso lo utiliza

Cualquier puerto TCP libre entre 1024 y 65535 sirve. Realice estas dos comprobaciones antes de decidirse por uno:

sudo ss -tlnp | grep -w 2222
sudo semanage port -l | grep -w 2222

La primera muestra si algún proceso ya está escuchando en ese número. La segunda muestra si la política de SELinux ya lo asigna a otro tipo de servicio. Un puerto libre no devuelve ninguna salida en ninguna de las dos comprobaciones. Si la política ya lo reclama, semanage port -a del paso 2 falla con ValueError: Port tcp/2222 already defined. La solución es elegir otro número.

En toda esta guía se usa 2222 como ejemplo. Además, es el primer puerto que prueba un escáner después del 22, por lo que en un servidor real debe elegir un número menos evidente.

Paso 1: abrir el puerto en firewalld

sudo firewall-cmd --permanent --add-port=2222/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports

--permanent escribe la regla en el archivo de zona del disco y no modifica el firewall en ejecución. --reload carga la configuración del disco en el firewall en ejecución. Si omite la recarga, la regla existe, pero no hace nada hasta que firewalld se reinicie. Esta es una de las formas más comunes en que todo el procedimiento parece fallar sin motivo.

Por ahora, no modifique la entrada del servicio ssh. Esa entrada mantiene abierto el puerto 22 y sirve como alternativa mientras realiza las pruebas.

Revise también el panel de control de su proveedor. Muchos proveedores ejecutan un firewall de red delante del VPS, fuera del sistema operativo. Por eso, un puerto que haya abierto en firewalld todavía puede ser descartado en un punto anterior de la red. La guía básica de firewalld para un VPS explica las zonas y la diferencia entre la configuración en ejecución y la configuración permanente si este modelo es nuevo para usted.

Paso 2: etiquetar el puerto para SELinux

sudo semanage port -a -t ssh_port_t -p tcp 2222
sudo semanage port -l | grep ssh_port_t

-a agrega una nueva asignación de puerto. -t ssh_port_t es el tipo que usan los puertos SSH. El segundo comando muestra todo lo que ssh_port_t cubre ahora, para que pueda confirmar que el número se registró antes de modificar el daemon.

Por qué SELinux bloquea el puerto

SELinux (security-enhanced Linux) asigna una etiqueta a cada objeto del sistema, y los números de puerto TCP son objetos como cualquier otro. El daemon SSH se ejecuta confinado en un dominio llamado sshd_t. La política permite que sshd_t establezca enlaces en puertos TCP etiquetados como ssh_port_t, y de forma predeterminada el único puerto que tiene esa etiqueta es el 22. Si se solicita al daemon que establezca un enlace en 2222, el kernel comprueba la etiqueta, encuentra el tipo genérico que la política asignó a ese número y rechaza el permiso name_bind en el socket.

Por eso este fallo no parece un problema del firewall. El kernel rechaza la operación antes de que exista un socket en escucha, por lo que sshd informa del error y termina. Un problema del firewall es lo contrario: el daemon está en ejecución y funciona correctamente, pero los paquetes se descartan al entrar.

getenforce indica en qué modo está el sistema. En Permissive se registra una denegación, pero no se aplica, por lo que el cambio de puerto parece funcionar y después falla cuando alguien ejecuta setenforce 1 o el sistema arranca de nuevo en modo enforcing. Etiquete el puerto en cualquier caso. La guía básica de SELinux para servidores explica correctamente los modos, los contextos y los booleanos. Los puertos no son los únicos objetos afectados. La misma política impide que un contenedor lea un directorio del host montado hasta que se vuelva a etiquetar esa ruta. Por eso la instalación de Docker en Rocky Linux o AlmaLinux incluye un paso de SELinux que las guías de Ubuntu nunca mencionan.

Paso 3: establezca el puerto en la configuración de sshd

En Rocky Linux 9 y 10, AlmaLinux 9 y 10 y las versiones actuales de Fedora, /etc/ssh/sshd_config comienza con una línea include, por lo que el lugar adecuado para el cambio es un archivo drop-in. Las actualizaciones de paquetes no entrarán en conflicto con su modificación.

grep -n '^Include' /etc/ssh/sshd_config
echo 'Port 2222' | sudo tee /etc/ssh/sshd_config.d/10-port.conf
sudo sshd -t

Si grep no encuentra ninguna línea Include, como ocurre en Rocky Linux 8 y en otras imágenes antiguas, introduzca Port 2222 directamente en /etc/ssh/sshd_config. sshd -t analiza toda la configuración, incluidos los archivos drop-in, e informa de los errores de sintaxis. Corrija cualquier error que informe antes de reiniciar, porque una configuración que no se puede analizar impide que el daemon vuelva a iniciarse.

Port puede aparecer más de una vez, y sshd escucha en todos los puertos indicados. Mantener Port 22 junto a Port 2222 durante el primer día es una medida de seguridad sencilla, siempre que recuerde eliminarlo.

¿sshd se inicia mediante una unidad de socket?

Algunas imágenes inician SSH mediante la activación de sockets de systemd en lugar de ejecutarlo como un servicio de larga duración. Cuando está configurado de esta forma, systemd administra el socket de escucha y entrega las conexiones a sshd, por lo que la línea Port de sshd_config se ignora por completo. Compruébelo antes de reiniciar nada:

systemctl is-enabled sshd.socket

Una respuesta enabled indica que el puerto está definido en la unidad de socket, no en sshd_config:

sudo systemctl edit sshd.socket
[Socket]
ListenStream=
ListenStream=2222

El ListenStream= sin valores es obligatorio. Los valores se acumulan entre los archivos drop-in. Si no asigna primero un valor vacío para borrar la lista, el socket seguirá escuchando en 22 y 2222. Aplique el cambio con sudo systemctl daemon-reload y después con sudo systemctl restart sshd.socket. Si la unidad está deshabilitada o no existe en su servidor, esta sección no se aplica a su caso.

Paso 4: reinicie y pruebe desde un segundo terminal

sudo systemctl restart sshd
systemctl status sshd
sudo ss -tlnp | grep sshd

Mantenga este terminal abierto. No cierre la sesión. Abra un segundo terminal en su propio equipo y conéctese al nuevo puerto:

ssh -p 2222 youruser@203.0.113.10

Cierre la primera sesión sólo después de que el segundo inicio de sesión funcione. Si no funciona, todavía tendrá un shell desde el que podrá revertir todos los cambios. Este hábito marca la diferencia entre un cambio de cinco minutos y pasar toda la tarde en la consola del proveedor.

¿Firewall drop o rechazo de SELinux? Cómo distinguirlos

Desde el portátil, los dos fallos parecen casi idénticos. En el servidor no se parecen en nada.

  • Si systemctl status sshd muestra que la unidad ha fallado, el daemon nunca obtuvo su socket. Es un error de configuración o un rechazo de SELinux.
  • Si la unidad está activa y ss -tlnp muestra que sshd está enlazado al puerto nuevo, el daemon funciona y el problema está en la ruta de red: firewalld, el firewall independiente del proveedor o la dirección y el puerto que indicó.

Para el caso de SELinux, lea el registro de auditoría en lugar de hacer suposiciones:

sudo ausearch -m AVC -ts recent
sudo journalctl -u sshd -n 50 --no-pager

Un rechazo name_bind en la clase tcp_socket indica el proceso en comm="sshd", el número de puerto en src= y la etiqueta que tiene realmente el puerto en tcontext=. Este último campo contiene la respuesta. Cualquier valor distinto de ssh_port_t significa que el paso 2 no se aplicó al puerto que usa, normalmente por un error tipográfico en el número o por usar el protocolo incorrecto. Instale setroubleshoot-server si prefiere que sealert convierta el registro en una frase.

El mensaje que sshd escribe cuando el kernel rechaza el enlace tiene este aspecto:

error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.

Permission denied en un puerto superior a 1024, donde no se necesitan privilegios de root para enlazarlo, es la firma de SELinux. Address already in use en esa misma línea indica un fallo diferente: otro proceso está ocupando el puerto. Desde el cliente, la diferencia entre una conexión rechazada y una conexión cuyo tiempo de espera se agota permite distinguir los dos casos de red, porque un rechazo significa que el paquete llegó al host y no había ningún proceso escuchando, mientras que un tiempo de espera agotado significa que no respondió nada.

Cierre el puerto 22 y actualice los clientes

Cuando varias conexiones en el puerto nuevo hayan funcionado, quite el puerto 22:

sudo firewall-cmd --permanent --remove-service=ssh
sudo firewall-cmd --reload
sudo firewall-cmd --list-all

No modifique la etiqueta de SELinux del puerto 22. Proviene de la política base y no concede ningún acceso cuando el firewall deja de aceptar paquetes entrantes.

Después, actualice los clientes, porque debe indicar el puerto a todas las herramientas que daban por supuesto el puerto predeterminado. Configúrelo una vez en ~/.ssh/config en su propia máquina, en lugar de escribir -p continuamente:

Host myvps
  HostName 203.0.113.10
  Port 2222
  User youruser

scp, sftp, rsync y Ansible leen ese archivo. Los trabajos de copia de seguridad, las comprobaciones de monitorización y los scripts de cron que tienen el puerto 22 escrito directamente no lo hacen. Localícelos mientras el cambio aún está reciente.

Qué resuelve y qué no resuelve cambiar el puerto

Reduce el ruido en los registros. Los escáneres automatizados atacan constantemente el puerto 22, y cambiar a otro elimina la mayoría de esas líneas del journal. Así resulta más fácil detectar los eventos reales. No es un control de seguridad. Cualquier escáner que recorra todo el rango de puertos encuentra el daemon y lee igualmente su banner de versión. Considere el cambio de puerto una tarea de mantenimiento. Aplique la protección real mediante autenticación exclusiva con claves y desactive los inicios de sesión con contraseña. La guía de refuerzo de SSH para un VPS explica este proceso paso a paso.

Todo lo anterior funciona igual en las dos principales reconstrucciones de RHEL, porque se compilan a partir de las mismas fuentes. Consulte Rocky Linux y AlmaLinux comparados si todavía está eligiendo entre ambas. Existen dos reconstrucciones casi idénticas entre las que elegir porque CentOS dejó de serlo en 2020. La historia de Red Hat a CentOS, Rocky y AlmaLinux explica este cambio en detalle. Compruebe qué versión recibió realmente antes de seguir una guía antigua, mediante cat /etc/os-release. Las guías escritas para Rocky Linux 8 todavía aparecen entre los primeros resultados y sus pasos semanage y firewall-cmd siguen siendo correctos. Sin embargo, Rocky 8 no tiene ninguna línea de inclusión sshd_config.d ni una unidad de socket que deba tener en cuenta. Por eso, la parte sobre sshd de esas guías no coincide con un sistema actual.

hay que indicar a fail2ban el nuevo puerto

fail2ban no está disponible en los repositorios base. Se obtiene de EPEL (paquetes adicionales para Enterprise Linux):

sudo dnf install -y epel-release
sudo dnf install -y fail2ban fail2ban-firewalld

El subpaquete fail2ban-firewalld hace que fail2ban aplique sus bloqueos mediante firewalld. Esto es lo adecuado en un sistema donde firewalld administra el conjunto de reglas.

La jail estándar sshd establece port = ssh. Ese nombre se resuelve mediante /etc/services en el puerto 22. Después del cambio, la jail supervisa un puerto que nadie está atacando. Por eso no bloquea a nadie mientras los intentos de inicio de sesión fallidos se acumulan en el puerto 2222. Establezca el puerto mediante su número en /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = 2222
backend = systemd
maxretry = 5
bantime = 3600

backend = systemd lee los fallos del journal en lugar de /var/log/secure. Es la opción más segura en una instalación mínima donde rsyslog puede no estar disponible. Inícielo con sudo systemctl enable --now fail2ban y revise la jail con sudo fail2ban-client status sshd. La sintaxis de la jail es la misma que se usa en la configuración de fail2ban para SSH en Ubuntu 24.04. Sólo difieren el origen del paquete y la acción de bloqueo.

Los parches importan más que el puerto

Un servidor con el puerto SSH cambiado y cuatro meses de actualizaciones de seguridad sin aplicar está en peor estado que uno que usa el puerto 22 y se actualiza automáticamente cada noche. Active las actualizaciones desatendidas en la misma sesión, mientras ya tiene una shell como root: actualizaciones automáticas de dnf en Rocky Linux y AlmaLinux explica el temporizador y la elección entre descargar las actualizaciones y aplicarlas. Una actualización instalada no reinicia los daemons que ya ejecutan el código anterior. Por eso, comprobar qué servicios aún necesitan un reinicio o un reinicio del sistema requiere apenas un minuto cuando openssh-server o una biblioteca de la que depende se incluye en el lote.

FAQ

¿Por qué sshd no inicia después de cambiar el puerto en Rocky Linux?

Casi siempre falta la etiqueta de puerto de SELinux. sshd se ejecuta confinado en el dominio sshd_t, y la política sólo le permite asociarse a puertos etiquetados como ssh_port_t, que de forma predeterminada sólo incluye el puerto 22. El kernel rechaza la asociación, por lo que el daemon termina en lugar de escuchar, y journalctl -u sshd contiene una línea con el formato error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.. Ejecute sudo semanage port -a -t ssh_port_t -p tcp 2222 con su propio número de puerto y reinicie el servicio. Si no encuentra semanage, instale primero policycoreutils-python-utils.

¿Sigue siendo necesario semanage si SELinux está en modo permisivo?

Sí. En modo permisivo, la denegación se registra y la asociación se permite de todos modos, por lo que parece que el cambio funcionó. La etiqueta sigue faltando. En cuanto alguien ejecuta setenforce 1, o el equipo arranca con SELINUX=enforcing en /etc/selinux/config, sshd deja de iniciar en ese puerto. Añadir la etiqueta requiere un comando y elimina un fallo que, de otro modo, podría aparecer semanas después sin una causa evidente.

El puerto tiene una etiqueta y sshd está en ejecución. ¿Por qué se agota el tiempo de espera de mi conexión?

Un daemon en ejecución indica que SELinux no bloquea la operación, por lo que el paquete se está descartando antes de llegar al sistema. Compruebe sudo firewall-cmd --list-ports para verificar su puerto y confirme que ejecutó firewall-cmd --reload después de la regla --permanent, porque una regla permanente por sí sola nunca se aplica al firewall en ejecución. Después, compruebe el panel de control de su proveedor para detectar si hay un firewall de red independiente delante del VPS. Ese es el segundo punto donde se bloquean las conexiones, y nada dentro del sistema operativo lo mostrará.

¿Qué puerto debería usar en lugar del 22?

Cualquier puerto TCP libre entre 1024 y 65535. Evite 2222 y 22222 en un servidor real, porque los escáneres los prueban inmediatamente después del 22. Confirme que el número está libre con sudo ss -tlnp, compruebe que la política de SELinux no lo haya asignado ya con sudo semanage port -l y evite cualquier puerto asignado a un servicio que pueda instalar más adelante. Un número alto y difícil de recordar es válido, porque lo escribirá una sola vez en ~/.ssh/config y no tendrá que volver a introducirlo.