Portknocking et tunneling SSH : les tours de magie d'avant WireGuard
En 2008, ce blog publiait Portknocking : l’art de frapper à la porte, puis la génération automatique de combinaisons , avec le tunneling SSH en étagère voisine. Fun, pédagogique et réellement déployé: je l’ai vu en entreprise jusqu’en 2018 chez un hébergeur. En 2016, Jason Donenfeld publie WireGuard et la question change de nature: pas “comment cacher la porte”, mais “pourquoi y a-t-il une porte?”.
Le montage de 2009, en souvenir ému
Pour les retardataires, ce que le portknocking “de luxe” de l’époque impliquait:
- une combinaison de ports calculée depuis la date système, la taille de port doublée jusqu’à dépasser 1024, plafonnée à 65535. Note: le schéma publié en 2009 était la version école, journalière. Le vrai, celui qui tournait, était à l’heure et à la minute et vivait dans
knock/funcsur la clé USB chiffrée encfs, jamais commité: on ne donne pas son sesame dans le mode d’emploi et le dépôt gobel1/bash le prouve à l’aveugle,kssh,kscp,kbckpet lesmountencfs dedans, pas un octet de la génération de séquence; - une synchronisation NTP obligatoire des deux côtés, puisque la combinaison est fonction de la fenêtre (article NTP du même blog, pratique);
- les fonctions
kssh/kscp/kbckpdans.bash_functions_mgmt, sourçant la combinaison depuisknock/funcsur la clé USB chiffrée encfs (smountmonte le.keysur.sdata), à la demande; - iptables côté serveur qui ouvre le port 22 à la séquence et le referme derrière.
Le tooling réel, exhumé du dépôt gobel1/bash (2012), montre le montage complet. L’encfs d’abord, la paire exacte du billet EncFS d’octobre 2008:
## Encfs, la paire du billet EncFS d'octobre 2008 (survit dans gobel1/bash)
function smount() {
encfs /home/logout/.key /home/logout/sdata; }
function sumount() {
fusermount -u /home/logout/sdata; }
## Knocking ssh
function kssh(){
host=`echo $* | egrep -o '([0-9]{1,3}\.)([0-9]{1,3}\.)([0-9]{1,3}\.)([0-9]{1,3})'`;
fqdn=`echo $* | egrep -o '([a-zA-Z0-9.-]+\.[a-zA-Z]{2,4})'`;
if [ -d /home/user/.sdata/coding/bash/ ];then
. /home/user/.sdata/coding/bash/knock/func;
else
smount && . /home/user/.sdata/coding/bash/knock/func;
fi
if [[ $host ]];then
/usr/bin/knock $host $toc && /usr/bin/ssh $*;
fi
unset toc host fqdn;
}
## knock rsync bckp
function kbckp(){
d="$1-`date +%y%m%d`";
kscp -rp vhalholl.info:www/$1 ~/.bckp/$d \
&& tar -vczf ~/.bckp/$d.tar.gz ~/.bckp/$d && rm -rf ~/.bckp/$d;
}
Et la génération de la combinaison, knock/func? Introuvable dans le dépôt, par construction: elle vivait dans .sdata/coding/bash/knock/func, sur la clé chiffrée, jamais commitée. Deux authenticités en prime: la version 2012 des fonctions a dérivé, smount cible /home/logout/.sdata/ pendant que kssh regarde /home/user/.sdata/ et sumount démonte /home/user/.sdata/ (trois chemins pour deux montages, le genre d’incohérence qui ne survit que dans un dépôt personnel sans CI) et le sshmount voisin renvoie à un autre billet, le SSH-FileSystem de mars 2009
. Quant à l’article EncFS d’octobre 2008
qui présentait ces deux fonctions, le voici: le tooling survit et sa documentation avec.
Toute la sécurité tenait dans trois prières: que le sniffer ne voie pas la séquence (il la voit: c’est du trafic réseau non chiffré, rejouable tant que la fenêtre n’a pas changé), que l’horloge ne dérive pas (elle dérive) et que personne ne note que le port 22 fermé répond toujours un RST poli. Le portknocking n’empêchait pas la détection: il ajoutait un tampon, à un problème qui n’en demandait pas.
Pourquoi c’était déplacé, sans être inutile
Le portknocking n’a jamais protégé sshd: il a surtout réduit le bruit de scan et, honnêtement, animé les soirées de règle iptables. En entreprise, chez un hébergeur, ça tenait debout parce que les pare-feux délimitaient déjà des zones: le knock était un rituel d’accès entre administrateurs, pas une défense. Face à un attaquant sérieux, la séquence se sniff, se rejoue et le vrai contrôle restait… l’authentification ssh. Autrement dit: toute la machinerie protégeait une couche qui se protégeait déjà mieux toute seule.
WireGuard: la porte se tait
WireGuard (2016) attaque le problème un niveau plus bas et c’est ce qui le rend déplacé face aux tours de magie:
- Il ne dit rien. Un paquet WireGuard vers un non-pair est simplement silencieusement ignoré: pas de RST, pas de SYN/ACK, rien. Un scan de port voit un trou noir, pas un service à casser. Le portknocking simulait le silence avec des règles iptables; WireGuard le fait dans le protocole.
- La crypto d’abord: protocole Noise, Curve25519, ChaCha20-Poly1305, BLAKE2s. L’identité est une clé publique, le handshake est authentifié avant toute révélation. Aucune information ne fuit avant l’authentification, c’est la définition du “crypto safe” que portknocking prétendait approcher avec des numéros de ports.
- ~4 000 lignes de code, auditable en un après-midi, contre la pile knockd + iptables + scripts de date + clé USB encfs.
- Roaming natif: l’adresse IP change, la session tient. Le tunneling SSH, lui, laisse tomber la connexion à chaque changement de réseau et TCP-over-TCP se venge dans les tunnels saturés.
Et le tunneling SSH? Il reste légitime pour ce qu’il est: un filet d’urgence, un pont rapide vers un service interne, un SOCKS à la volée. Ce qu’il ne peut plus être, c’est l’architecture d’accès d’un parc: pas de roaming, pas d’UDP et une surface d’attaque sshd exposée, exactement ce que WireGuard élimine en gardant ssh derrière.
La morale, piquante
En 2008, on frappait aux portes en morse et on s’en était fiers. En 2016, on a appris aux portes à se taire: une clé publique suffit et ce qui n’est pas pair n’existe pas. J’ai désarmé mon dernier portknocking de production en 2018; les iptables ont retrouvé leur dignité, le NTP a cessé d’être un composant de sécurité et personne n’a demandé de ramener la combinaison de ports. Le fun, lui, reste documenté: c’est le rôle de l’archive.
Et c’est exactement pourquoi aujourd’hui les services restent sur leurs ports standards: cacher ssh sur un port exotique ou frapper avant d’entrer ne rassure que le scanner de port paresseux et coûte une plomberie fragile. Un service sur son port standard, derrière une authentification forte et un VPN qui ne parle qu’aux pairs, c’est plus honnête, plus auditable et drôlement plus reposant à opérer. Nuance de 2026 pour les esprits taquins qui voudraient réinventer la cachette: le silence de WireGuard vaut face au scanner de port, mais le trafic se laisse toujours classifier par sa forme (tailles de paquets, cadence) par un DPI sérieux, donc le silence n’est pas l’anonymat. La nécrologie complète du 443 multiplexé est racontée dans l’article sslh .
Parce qu’il y a évidemment un mais et il est souriant: le chat et la souris ont recruté des ingénieurs. AmneziaWG, un fork de WireGuard, ajoute ce que le protocole n’a pas: des junk packets de taille aléatoire avant le handshake, des en-têtes de message personnalisables (les types 1/2/3/4 de WireGuard remplacés par des valeurs au choix, H1-H4) et du bourrage dans les handshakes (S1/S2), de sorte que la signature de forme que le DPI cherchait n’existe plus. La famille voisine fait autrement mais pareil: udp2raw déguise l’UDP en TCP avec un handshake forgé, wstunnel passe WireGuard dans un WebSocket sous vrai TLS avec un vrai SNI et Xray REALITY joue au plus fin en empruntant le handshake TLS d’un vrai site pour faire du trafic quelconque. Ces outils existent, fonctionnent et ont un emploi réel: les réseaux hostiles, la censure, les corridors où le VPN est interdit par la loi et pas par le bon sens.
La limite est honnête: c’est une course. Le DPI répond par le probing actif (se connecter et vérifier que le service ressemble à ce qu’il prétend être), par la détection statistique du bourrage, par la classification des junk packets et les ingénieurs de la dissimulation répondent en recopiant le vrai monde (REALITY transfère réellement le visiteur curieux vers le vrai site). En entreprise, en revanche, tout ce théâtre est contre-productif: on n’y combat pas la censure, on y combat sa propre auditabilité et le vigile qui confond vos junk packets avec vos builds est votre propre runner. Le camouflage est un outil de survie en réseau hostile, pas une stratégie de prod.
[edit: 2026] L’implémentation Ansible de tout ceci: le rôle wireguard .