guest@6admin.io:~$

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 .