SSD Nodes Learn 🎉 VPS dès $5.50/mois
Guides Matt ConnorPar Matt Connor

Modifier le port SSH avec SELinux et firewalld

Sur Rocky Linux, AlmaLinux ou Fedora, ouvrez firewalld, étiquetez le port SELinux puis modifiez sshd_config dans le bon ordre pour rester connecté.

Pourquoi la modification du port SSH nécessite trois étapes ici

Pour modifier le port SSH sur Rocky Linux, AlmaLinux, CentOS Stream ou Fedora, une seule modification ne suffit pas. Trois systèmes distincts déterminent chacun si une connexion sur le nouveau port fonctionne. firewalld décide si le paquet atteint la machine. SELinux décide si sshd a le droit d’écouter sur ce numéro de port. sshd_config détermine le port demandé par le daemon. Si vous oubliez l’étape SELinux, le daemon refuse de démarrer. Si vous oubliez l’étape firewalld, il démarre et écoute, mais personne ne peut le joindre.

Sur Ubuntu, cette opération se limite à une modification et à un redémarrage, car Ubuntu utilise AppArmor au lieu de SELinux et ne fournit aucun profil limitant les ports sur lesquels sshd peut écouter. Si ufw est actif, vous ajoutez une règle. C’est toute la différence. La famille RHEL installe firewalld actif et SELinux en mode enforcing sur une installation neuve, et tous deux tiennent compte des numéros de port.

Effectuez les opérations dans cet ordre pour maintenir votre session actuelle pendant toute la procédure :

  1. Ouvrez le nouveau port dans firewalld, en laissant le port 22 ouvert pour le moment.
  2. Ajoutez le label SELinux du nouveau port avec semanage.
  3. Définissez le port dans la configuration de sshd.
  4. Redémarrez sshd, puis connectez-vous sur le nouveau port depuis un deuxième terminal avant de fermer le premier.
Repérez la console web de votre fournisseur (VNC ou série) avant de commencer et vérifiez que vous pouvez vous y connecter. Cette console vous permettra de reprendre l’accès si la modification échoue. La modification d’un port est l’une des causes les plus fréquentes d’une perte d’accès à un serveur qu’un locataire vient de louer.

Installez d’abord semanage

semanage est l’outil qui modifie les paramètres de la politique SELinux. Une installation minimale de Rocky Linux ou d’AlmaLinux ne l’inclut pas. Il se trouve dans policycoreutils-python-utils.

sudo dnf install -y policycoreutils-python-utils

Exécuter la commande avant d’installer ce paquet renvoie sudo: semanage: command not found. C’est à ce moment que de nombreux lecteurs concluent que SELinux n’est pas installé et ignorent cette étape. SELinux est bien installé. Seul l’outil de gestion est absent. Si la syntaxe dnf est nouvelle pour vous, les équivalents des commandes dnf et apt permettent de la rapprocher de ce que vous connaissez déjà.

Choisissez un port et vérifiez qu’il n’est pas déjà utilisé

N’importe quel port TCP libre entre 1024 et 65535 convient. Effectuez ces deux vérifications avant de l’utiliser :

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

La première commande indique si un processus écoute déjà sur ce port. La seconde vérifie si la stratégie SELinux l’associe déjà à un autre type de service. Un port libre ne renvoie aucun résultat dans les deux cas. Si la stratégie l’utilise déjà, le semanage port -a de l’étape 2 échoue avec ValueError: Port tcp/2222 already defined. Il faut alors choisir un autre numéro.

2222 est utilisé comme exemple dans ce guide. C’est également le premier port qu’un scanner essaie après 22. Sur un serveur réel, choisissez donc un numéro moins évident.

Étape 1 : ouvrir le port dans firewalld

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

--permanent écrit la règle dans le fichier de zone sur le disque et ne modifie pas le pare-feu en cours d’exécution. --reload charge la configuration présente sur le disque dans le pare-feu en cours d’exécution. Si vous omettez le rechargement, la règle existe, mais elle reste inactive jusqu’au prochain redémarrage de firewalld. C’est l’une des causes les plus fréquentes de l’échec apparent de cette procédure.

Laissez l’entrée de service ssh telle quelle pour le moment. Cette entrée maintient le port 22 ouvert. Elle vous sert de solution de secours pendant les tests.

Vérifiez également le panneau de contrôle de votre fournisseur. De nombreux hébergeurs utilisent un pare-feu réseau devant le VPS, en dehors du système d’exploitation. Un port ouvert dans firewalld peut donc encore être bloqué en amont. Le guide des bases de firewalld pour un VPS explique les zones ainsi que la distinction entre la configuration runtime et la configuration permanente si ce modèle ne vous est pas familier.

Étape 2 : étiqueter le port pour SELinux

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

-a ajoute une nouvelle affectation de port. -t ssh_port_t est le type associé aux ports SSH. La deuxième commande liste tous les ports désormais couverts par ssh_port_t. Vous pouvez ainsi vérifier que votre numéro a bien été ajouté avant de modifier le daemon.

Pourquoi SELinux bloque le port

SELinux (security-enhanced Linux) attribue une étiquette à chaque objet du système, et les numéros de port TCP sont des objets comme les autres. Le démon SSH s’exécute dans un domaine confiné appelé sshd_t. La policy autorise sshd_t à se lier aux ports TCP portant l’étiquette ssh_port_t, et, par défaut, le seul port portant cette étiquette est 22. Si vous demandez au démon de se lier au port 2222, le kernel vérifie l’étiquette, trouve le type générique attribué par la policy à ce numéro et refuse la permission name_bind sur la socket.

C’est pourquoi cet échec ne ressemble pas à un problème de firewall. Le kernel refuse la demande avant même qu’une socket en écoute existe. sshd signale alors l’erreur et quitte. Un problème de firewall est l’image inverse : le démon fonctionne normalement et les paquets sont rejetés à leur arrivée.

getenforce indique dans quel mode se trouve le serveur. En mode Permissive, un refus est enregistré mais n’est pas appliqué. Le changement de port semble donc fonctionner, puis cesse de fonctionner le jour où quelqu’un exécute setenforce 1 ou lorsque le serveur redémarre en mode enforcing. Étiquetez le port dans tous les cas. Le guide de base de SELinux pour un serveur explique correctement les modes, les contextes et les booléens.

Étape 3 : définir le port dans la configuration de sshd

Sur Rocky Linux 9 et 10, AlmaLinux 9 et 10, ainsi que sur les versions actuelles de Fedora, /etc/ssh/sshd_config commence par une ligne include. L’emplacement propre pour votre modification est donc un fichier drop-in. Les mises à jour des paquets ne risquent ainsi jamais d’écraser votre modification.

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 ne trouve aucune ligne Include, ce qui est le cas sur Rocky Linux 8 et d’autres images plus anciennes, ajoutez directement Port 2222 dans /etc/ssh/sshd_config. sshd -t analyse toute la configuration, y compris les drop-ins, et signale les erreurs de syntaxe. Corrigez toutes les erreurs signalées avant de redémarrer, car une configuration impossible à analyser empêche le daemon de redémarrer.

Port peut apparaître plusieurs fois, et sshd écoute sur chaque port indiqué. Conserver Port 22 en parallèle de Port 2222 pendant le premier jour constitue une sécurité simple, à condition de penser à le supprimer.

Votre sshd est-il démarré par une unité socket ?

Certaines images démarrent SSH via l’activation par socket de systemd, plutôt que comme un service exécuté en continu. Dans ce cas, systemd gère la socket en écoute et transmet les connexions à sshd. La ligne Port dans sshd_config est donc entièrement ignorée. Vérifiez ce point avant de redémarrer quoi que ce soit :

systemctl is-enabled sshd.socket

Une réponse enabled signifie que le port est défini dans l’unité socket, et non dans sshd_config :

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

La directive ListenStream= sans valeur est nécessaire. Les valeurs se cumulent dans les fichiers drop-in. Sans affectation vide pour commencer par vider la liste, la socket continue donc à écouter sur 22 ainsi que sur 2222. Appliquez la modification avec sudo systemctl daemon-reload, puis avec sudo systemctl restart sshd.socket. Si l’unité est désactivée ou absente de votre serveur, cette section ne vous concerne pas.

Étape 4 : redémarrez, puis testez depuis un deuxième terminal

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

Gardez ce terminal ouvert. Ne vous en déconnectez pas. Ouvrez un deuxième terminal sur votre propre machine et connectez-vous au nouveau port :

ssh -p 2222 youruser@203.0.113.10

Ne fermez la première session qu’après la réussite de cette deuxième connexion. Si la connexion échoue, vous disposez encore d’un shell depuis lequel vous pouvez tout annuler. Cette habitude fait la différence entre une modification de cinq minutes et un après-midi passé sur la console du fournisseur.

Pare-feu qui bloque ou refus SELinux ? Comment les distinguer

Depuis votre laptop, les deux échecs semblent presque identiques. Sur le serveur, ils n’ont rien à voir.

  • Si systemctl status sshd indique que l’unité a échoué, le daemon n’a jamais obtenu son socket. Il s’agit d’une erreur de configuration ou d’un refus SELinux.
  • Si l’unité est active et que ss -tlnp indique que sshd écoute sur le nouveau port, le daemon fonctionne. Le problème se situe sur le chemin réseau : firewalld, le pare-feu distinct du fournisseur, ou l’adresse et le port utilisés.

Dans le cas de SELinux, consultez l’enregistrement d’audit au lieu de supposer :

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

Un refus name_bind sur la classe tcp_socket indique le processus dans comm="sshd", le numéro de port dans src= et le label réellement associé au port dans tcontext=. Ce dernier champ donne la réponse. Toute valeur autre que ssh_port_t signifie que l’étape 2 ne s’appliquait pas au port utilisé, généralement à cause d’une erreur dans le numéro ou de l’utilisation du mauvais protocole. Installez setroubleshoot-server si vous préférez que sealert transforme l’enregistrement en phrase.

Le message écrit par sshd lui-même lorsque le kernel refuse le bind ressemble à ceci :

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

Permission denied sur un port supérieur à 1024, pour lequel aucun privilège root n’est nécessaire pour effectuer le bind, est la signature de SELinux. Address already in use dans cette même ligne indique un autre problème : un autre processus utilise déjà le port. Depuis le client, la différence entre une connexion refusée et une connexion qui expire permet de distinguer les deux cas réseau : un refus signifie que votre paquet a atteint l’hôte et qu’aucun processus n’écoutait, tandis qu’un timeout signifie que personne n’a répondu.

Fermez le port 22 et mettez à jour vos clients

Après plusieurs connexions réussies sur le nouveau port, retirez le port 22 :

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

Ne modifiez pas le label SELinux du port 22. Il provient de la policy de base et n’autorise plus rien dès que le pare-feu bloque les paquets entrants.

Mettez ensuite à jour les clients. Tous les outils qui utilisent le port par défaut doivent maintenant recevoir cette information. Ajoutez-la une seule fois dans ~/.ssh/config sur votre propre machine, au lieu de saisir -p à chaque fois :

Host myvps
  HostName 203.0.113.10
  Port 2222
  User youruser

scp, sftp, rsync et Ansible lisent tous ce fichier. Les tâches de sauvegarde, les contrôles de supervision et les scripts cron qui imposent le port 22 ne le lisent pas. Recherchez-les pendant que la modification est encore récente.

Ce que le changement de port apporte ou non

Il réduit le bruit dans les journaux. Les scanners automatisés martèlent constamment le port 22. L’utiliser sur un autre port supprime la plupart de ces lignes du journal, ce qui permet de repérer plus facilement les événements réels. Ce n’est pas une mesure de sécurité. Tout scanner qui balaie toute la plage de ports trouve votre daemon et lit de toute façon sa bannière de version. Considérez le changement de port comme une tâche d’administration courante. Mettez en place la véritable protection avec une authentification par clé uniquement et désactivez les connexions par mot de passe. Le guide de durcissement SSH pour un VPS présente cette procédure étape par étape.

Tout ce qui précède fonctionne de manière identique sur les deux principales reconstructions de RHEL, car elles sont produites à partir des mêmes sources. Consultez Comparaison de Rocky Linux et AlmaLinux si vous hésitez encore entre les deux. Vérifiez quelle version vous a réellement été fournie avant de suivre un guide plus ancien, avec cat /etc/os-release. Les guides rédigés pour Rocky Linux 8 restent bien référencés, et leurs étapes semanage et firewall-cmd restent correctes. Cependant, Rocky 8 ne contient aucune ligne include sshd_config.d ni unité socket à prendre en compte. La partie consacrée à sshd dans ces guides ne correspond donc pas à une machine actuelle.

fail2ban doit connaître le nouveau port

fail2ban ne se trouve pas dans les dépôts de base. Il provient d’EPEL (Extra Packages for Enterprise Linux) :

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

Le sous-paquet fail2ban-firewalld demande à fail2ban d’appliquer ses bannissements via firewalld. C’est ce qu’il faut utiliser sur un serveur où firewalld gère le ruleset.

La jail sshd fournie par défaut définit port = ssh. Ce nom est résolu par /etc/services vers le port 22. Après votre modification, la jail surveille un port que personne n’attaque. Elle ne bannit donc personne, tandis que les échecs de connexion s’accumulent sur le port 2222. Définissez le port avec son numéro dans /etc/fail2ban/jail.local :

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

backend = systemd lit les échecs dans le journal plutôt que dans /var/log/secure. C’est le choix le plus sûr sur une installation minimale, où rsyslog peut être absent. Démarrez-le avec sudo systemctl enable --now fail2ban, puis inspectez la jail avec sudo fail2ban-client status sshd. La syntaxe de la jail est la même que celle utilisée dans la configuration de fail2ban pour SSH sur Ubuntu 24.04. Seule la source du paquet et l’action de bannissement diffèrent.

Les correctifs sont plus importants que le port

Un serveur dont le port SSH a été changé et qui n’a pas installé de mises à jour de sécurité depuis quatre mois est dans un état plus risqué qu’un serveur qui écoute sur le port 22 et installe automatiquement ses correctifs chaque nuit. Activez les mises à jour automatiques pendant la même session, puisque vous êtes déjà connecté en tant que root : mises à jour automatiques avec dnf sur Rocky Linux et AlmaLinux explique la configuration du timer et le choix entre télécharger les mises à jour et les installer.

FAQ

Pourquoi sshd refuse-t-il de démarrer après la modification du port sur Rocky Linux ?

Dans presque tous les cas, il manque le label de port SELinux. sshd s’exécute dans le domaine sshd_t, et la policy l’autorise uniquement à lier des ports portant le label ssh_port_t, qui correspond par défaut au seul port 22. Le kernel refuse le bind. Le daemon s’arrête donc au lieu de se mettre en écoute, et journalctl -u sshd contient une ligne de la forme error: Bind to port 2222 on 0.0.0.0 failed: Permission denied.. Exécutez sudo semanage port -a -t ssh_port_t -p tcp 2222 avec votre propre numéro de port, puis redémarrez le service. Si semanage est introuvable, installez d’abord policycoreutils-python-utils.

Ai-je encore besoin de semanage si SELinux est en mode permissif ?

Oui. En mode permissif, le refus est journalisé et le bind est tout de même autorisé. La modification semble donc fonctionner. Le label manque toujours. Dès que quelqu’un exécute setenforce 1, ou que la machine démarre avec SELINUX=enforcing dans /etc/selinux/config, sshd cesse de démarrer sur ce port. Ajouter le label ne nécessite qu’une commande et supprime une cause de panne qui pourrait sinon apparaître plusieurs semaines plus tard, sans cause évidente.

Le port est correctement labellisé et sshd fonctionne. Pourquoi ma connexion expire-t-elle ?

Un daemon en fonctionnement signifie que SELinux autorise le bind. Le paquet est donc bloqué en amont. Vérifiez sudo firewall-cmd --list-ports pour votre port. Confirmez également que vous avez exécuté firewall-cmd --reload après la règle --permanent, car une règle persistante seule ne s’applique jamais au firewall en cours d’exécution. Vérifiez ensuite le panneau de contrôle de votre hébergeur pour détecter la présence d’un firewall réseau distinct devant le VPS. C’est le deuxième endroit où les connexions sont souvent bloquées. Rien dans le système d’exploitation ne l’indiquera.

Quel port utiliser à la place du port 22 ?

Utilisez n’importe quel port TCP libre compris entre 1024 et 65535. Évitez 2222 et 22222 sur un serveur réel, car les scanners les testent immédiatement après le port 22. Vérifiez que le numéro est libre avec sudo ss -tlnp. Confirmez que la policy SELinux ne l’utilise pas déjà avec sudo semanage port -l. Évitez également les ports attribués à un service que vous pourriez installer ultérieurement. Un numéro élevé et difficile à mémoriser convient, car vous l’écrirez une seule fois dans ~/.ssh/config et vous n’aurez plus à le saisir.