Un développeur avec qui j’échangeais récemment m’a posé une question simple : est-ce que ça sert vraiment à quelque chose de changer le port SSH par défaut ? La discussion a dérivé, et je me suis retrouvé à lui parler de port knocking.
C’est un sujet que j’avais creusé quelques mois plus tôt pour mon homelab. NAS Synology, quelques VMs sur Proxmox, un besoin d’accès distant ponctuel. Laisser le port 22 grand ouvert en permanence, très peu pour moi.
Le port knocking était une des briques que j’avais mises en place. Voilà ce que j’en ai retenu.
Le principe
Le port knocking, c’est une séquence de paquets envoyés sur des ports fermés avant d’ouvrir l’accès au vrai service. Un peu comme un code frappé à une porte : toc-toc-toc, et la porte s’ouvre.
Concrètement, le serveur écoute sur plusieurs ports (fermés, donc invisibles pour un scan classique). Quand il reçoit les paquets dans le bon ordre, il déverrouille le port 22 pour l’IP qui a frappé. Le temps passe, et le port se referme.
Pour un attaquant qui scanne, le port 22 est simplement fermé. Il n’a aucun moyen de savoir qu’une séquence précise de paquets pourrait l’ouvrir. C’est de la sécurité par l’obscurité, assumée comme première couche.
Mise en place avec knockd
knockd est le démon de port knocking le plus répandu. Il est dans les dépôts de la plupart des distributions.
sudo apt install knockd
La configuration se fait dans /etc/knockd.conf :
[options]
UseSyslog
Interface = eth0
[openSSH]
sequence = 7000,8000,9000
seq_timeout = 5
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
[closeSSH]
sequence = 9000,8000,7000
seq_timeout = 5
command = /sbin/iptables -D INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
Quelques explications :
- sequence : les trois ports sur lesquels il faut frapper, dans l’ordre. On peut en mettre plus ou moins, et utiliser TCP ou UDP.
- seq_timeout : le temps maximum, en secondes, pour envoyer la séquence complète. Passé ce délai, on recommence à zéro.
- %IP% : remplacé automatiquement par l’adresse IP source de la machine qui a frappé. La règle iptables n’ouvre le port que pour cette IP spécifique.
- tcpflags = syn : seuls les paquets SYN sont pris en compte. Un scan qui enverrait des paquets aléatoires ne déclencherait rien.
La séquence de fermeture est optionnelle mais pratique. Sans elle, le port reste ouvert jusqu’à ce qu’on nettoie manuellement la règle iptables, ou jusqu’à ce qu’un cron la supprime.
On active le démon :
# Dans /etc/default/knockd, s'assurer que START_KNOCKD=1
sudo systemctl enable --now knockd
La règle iptables par défaut
Avant d’activer knockd, il faut s’assurer que le port 22 est fermé par défaut. La règle qu’ajoute [openSSH] ne sert à rien si le port est déjà ouvert.
# Refuser tout trafic entrant sur le port 22
sudo iptables -A INPUT -p tcp --dport 22 -j DROP
Attention : à faire après avoir configuré knockd, et idéalement depuis une console locale. Si la règle est en place et que knockd ne fonctionne pas, on perd l’accès SSH.
Frapper depuis le client
Côté client, on utilise l’outil knock (fourni avec le paquet knockd) :
# Installer knockd (qui fournit aussi le client knock)
sudo apt install knockd
# Frapper
knock <ip_serveur> 7000 8000 9000
On peut aussi utiliser netcat, pour les allergiques aux dépendances supplémentaires :
for port in 7000 8000 9000; do
nc -z -w1 <ip_serveur> $port
done
Le -z de netcat envoie un paquet sans attendre de réponse (mode scan). Le résultat est le même qu’avec knock : des paquets SYN sur les ports spécifiés, dans l’ordre.
Ce que ça protège, et ce que ça ne protège pas
Le port knocking ajoute une couche d’obscurité. Pas une couche de chiffrement. Ce n’est pas un substitut à une bonne configuration SSH : clés à la place des mots de passe, pas de root login, éventuellement un port non standard.
Ce que ça fait bien :
- Réduire la surface d’attaque. Un scanner de masse ne voit pas le port 22. Point barre.
- Éliminer le bruit dans les logs. Plus de tentatives automatiques de brute-force. Les logs SSH redeviennent lisibles.
- Ajouter une étape avant l’authentification. Pour un attaquant ciblé, il faut d’abord deviner la séquence, puis contourner SSH. Une barrière de plus, pas une garantie.
Ce que ça ne fait pas :
- Protéger contre un attaquant qui écoute le trafic. La séquence est transmise en clair. Quelqu’un qui capture les paquets réseau peut la rejouer.
- Remplacer un VPN. Si l’accès doit être permanent et multi-utilisateurs, un WireGuard sera plus robuste et plus simple à gérer.
C’est pour ça que je le combine systématiquement avec fail2ban. Le port knocking coupe le bruit de fond, fail2ban bloque les tentatives insistantes. Les deux ensemble font un filet raisonnable pour un usage homelab.
# /etc/fail2ban/jail.local
[sshd]
enabled = true
port = 22
maxretry = 3
bantime = 3600
Trois tentatives échouées, une heure de bannissement. Avec le port knocking en amont, fail2ban n’a presque plus rien à faire. Il est là au cas où, et c’est une brique que j’active systématiquement sur toute machine exposée.
Aller plus loin
Sans knockd : iptables et le module recent
Knockd est pratique, mais il ajoute une dépendance. On peut obtenir le même résultat avec iptables seul, en utilisant le module recent.
Le principe : on marque les IPs qui frappent aux bons ports, dans le bon ordre. Chaque règle vérifie que l’étape précédente a été franchie avant de passer à la suivante.
# Étape 1 : marquer l'IP qui frappe sur 7000
iptables -A INPUT -p tcp --dport 7000 -m recent --name KNOCK1 --set -j DROP
# Étape 2 : si l'IP a le tag KNOCK1 et frappe sur 8000, passer à KNOCK2
iptables -A INPUT -p tcp --dport 8000 -m recent --rcheck --name KNOCK1 -m recent --name KNOCK2 --set -j DROP
# Étape 3 : si l'IP a le tag KNOCK2 et frappe sur 9000, autoriser SSH
iptables -A INPUT -p tcp --dport 9000 -m recent --rcheck --name KNOCK2 -m recent --name ALLOWED --set -j DROP
# Autoriser SSH pour les IPs dans la liste ALLOWED
iptables -A INPUT -p tcp --dport 22 -m recent --rcheck --seconds 300 --name ALLOWED -j ACCEPT
# Fermer le port 22 pour tout le reste
iptables -A INPUT -p tcp --dport 22 -j DROP
Le --seconds 300 sur la règle SSH limite l’accès à 5 minutes après le knock. Passé ce délai, l’IP n’est plus reconnue comme autorisée et il faut refrapper la séquence.
L’avantage : zéro dépendance externe, tout passe par le firewall. L’inconvénient : pas de séquence de fermeture explicite, pas de logging intégré (il faut ajouter des règles -j LOG si on veut tracer). Pour un usage simple, ça fait le job.
Double port knocking
On peut aussi chaîner deux séquences. Une première ouvre un port intermédiaire, une seconde déverrouille l’accès SSH.
Avec knockd :
[openIntermediate]
sequence = 7000,8000,9000
seq_timeout = 5
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 7122 -j ACCEPT
tcpflags = syn
[openSSH]
sequence = 7122
seq_timeout = 5
command = /sbin/iptables -A INPUT -s %IP% -p tcp --dport 22 -j ACCEPT
tcpflags = syn
Côté client, on enchaîne les deux knock :
knock <ip_serveur> 7000 8000 9000
knock <ip_serveur> 7122
ssh user@<ip_serveur>
Pour un homelab, c’est clairement overkill. Une séquence simple suffit à éliminer le bruit des scanners automatiques. Mais le principe est là, et c’est une option si on veut pousser le concept.
SPA et fwknop
Le port knocking classique a une faiblesse : la séquence est prévisible si on peut observer le trafic. Le SPA (Single Packet Authorization) répond à ça.
Au lieu d’envoyer une séquence de paquets sur plusieurs ports, le SPA envoie un seul paquet, chiffré et signé. Le serveur le déchiffre, vérifie la signature, et ouvre le port si tout est valide. Impossible à rejouer, impossible à deviner.
L’outil de référence est fwknop (Firewall Knock Operator). Le principe est le même que knockd : on frappe avant d’entrer, mais avec une couche cryptographique qui change la donne.
# Côté serveur
sudo apt install fwknop-server
# Côté client
sudo apt install fwknop-client
# Envoyer une autorisation
fwknop -A tcp/22 -a <ip_source> -D <ip_serveur>
Pour un homelab, knockd suffit largement. Le SPA devient pertinent quand la menace passe d’automatisée à ciblée : un serveur exposé professionnellement, ou une infrastructure qui manipule des données sensibles.
Le port knocking n’est pas une solution miracle. C’est une première couche, simple à mettre en place, qui supprime le bruit et réduit la surface exposée. Combiné à des clés SSH ed25519 et fail2ban, ça donne un niveau de sécurité correct pour un accès distant occasionnel.
Et honnêtement, ne plus avoir des logs SSH saturés de tentatives de connexion automatiques, rien que pour ça, ça vaut le coup.
