Portknocking : génération automatique de combinaisons
Le portknocking classique frappe à la porte avec une séquence de ports fixe. Le problème d’une séquence fixe: elle se sniff, elle se rejoue. La solution: faire dépendre la séquence de la date, pour qu’elle change chaque jour.
Le principe
La combinaison est calculée depuis la date système. Le jour détermine le protocole (pair = udp, impair = tcp) et les ports partent de la somme jour+mois+année doublée, à laquelle on ajoute 64 jusqu’à dépasser 1024. Le client et le serveur doivent avoir la même horloge, d’où la synchronisation NTP.
Le script
#!/bin/bash
: << 'TITLE.sh'
Version: 0.2
Authors: nobody@vhalholl.info
Description: Automatic portknocking sequence generation
Dependencies: knock, bc, ntp
TITLE.sh
A=$(date +%d); B=$(date +%m); C=$(date +%y)
S=$((A + B + C))
# Base: la somme des champs de date, doublée (puis +64 plus bas jusqu'à dépasser 1024)
P1=$((S * 2)); P2=$((P1 + 2)); P3=$((P2 + 2))
while [ $P1 -lt 1024 ]; do P1=$((P1 + 64)); done
while [ $P2 -lt 1024 ]; do P2=$((P2 + 64)); done
while [ $P3 -lt 1024 ]; do P3=$((P3 + 64)); done
# Borne haute: 65535
if [ $P1 -gt 65535 ]; then P1=65535; fi
if [ $P2 -gt 65535 ]; then P2=65535; fi
if [ $P3 -gt 65535 ]; then P3=65535; fi
# Protocole selon la parité du jour
if [ $((A % 2)) -eq 0 ]; then PROTO1="udp"; else PROTO1="tcp"; fi
if [ $((A % 2)) -eq 0 ]; then PROTO2="udp"; else PROTO2="tcp"; fi
if [ $((A % 2)) -eq 0 ]; then PROTO3="udp"; else PROTO3="tcp"; fi
# Frapper
knock $1 $P1:$PROTO1 $P2:$PROTO2 $P3:$PROTO3
Le script calcule la combinaison depuis le jour, le mois et l’année, détermine le protocole selon la parité et frappe. Le serveur (knockd) a la même logique de calcul et iptables ouvre le port 22 quand la séquence arrive dans l’ordre.
Les fonctions kssh/kscp
Les fonctions dans .bash_functions_mgmt lisent la combinaison depuis knock/func sur la clé USB chiffrée encfs:
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;
}
Le smount monte la clé encfs si elle n’est pas déjà montée, le knock/func génère $toc (la combinaison du jour) et le knock frappe avant le ssh. Le unset à la fin nettoie le sesame de la session.
[edit: 2026] Ce montage est mort depuis WireGuard (l’épilogue ), mais le pattern (séquence dérivée du temps + chiffrement de la clé + NTP) est resté dans la mémoire. Le portknocking simple était un trick de 2008; la version automatisée était un exercice de style qui a enseigné le NTP, le chiffrement de clé USB et la discipline de ne jamais stocker le sesame en clair.
[edit: 2026] L’implémentation Ansible de tout ceci: le rôle wireguard .