Déverrouiller un disque chiffré à distance avec un tunnel SSH inversé
Objectif : ne plus avoir à venir physiquement devant le serveur pour taper le code de déchiffrement LUKS à chaque redémarrage.
Au démarrage, le serveur chiffré ouvre lui-même un tunnel SSH vers un serveur relais joignable depuis Internet. Il suffit ensuite de se connecter au relais et de passer par le tunnel pour taper le code. Aucun port n’est à ouvrir sur la box du serveur chiffré.
serveur chiffré (initramfs) ──── tunnel SSH ────► relais:10022
Dropbear :4748 ◄──────────────────── ssh -p 10022 root@localhost
Prérequis :
- Serveur chiffré sous Debian 13 (trixie) avec le disque système chiffré en LUKS et
initramfs-tools- Un relais avec une IP publique ou un nom de domaine, et OpenSSH
- Dans ce tuto, le SSH du relais écoute sur le port
2022et le tunnel utilise le port10022. Remplacerrelais.exemple.frpar le nom du relais.
1. Installer Dropbear dans l’initramfs (serveur chiffré)
Dropbear est un petit serveur SSH qui tourne au démarrage, avant le déchiffrement du disque.
- Installer le paquet :
apt install dropbear-initramfs
- Configurer Dropbear :
vim /etc/dropbear/initramfs/dropbear.conf
- Ajouter la ligne :
DROPBEAR_OPTIONS="-I 180 -j -k -p 4748 -s -c cryptroot-unlock"
| Option | Rôle |
|---|---|
-I 180 |
Coupe la session après 180 s d’inactivité |
-j -k |
Interdit les redirections de ports |
-p 4748 |
Écoute sur le port 4748 |
-s |
Interdit la connexion par mot de passe (clé uniquement) |
-c cryptroot-unlock |
Lance directement la demande du code de déchiffrement |
- Les clés publiques autorisées à se connecter vont dans :
vim /etc/dropbear/initramfs/authorized_keys
La clé du relais y sera ajoutée à l’étape 4.
2. Préparer le relais
Créer un compte dédié au tunnel
- Créer un utilisateur sans shell :
adduser --disabled-password --shell /usr/sbin/nologin --gecos "" tunnel
mkdir -p /home/tunnel/.ssh
touch /home/tunnel/.ssh/authorized_keys
chown -R tunnel: /home/tunnel/.ssh
chmod 700 /home/tunnel/.ssh
chmod 600 /home/tunnel/.ssh/authorized_keys
Brider le compte
- Ajouter tout en bas de la config SSH :
vim /etc/ssh/sshd_config
Match User tunnel
AllowTcpForwarding remote
PermitTTY no
X11Forwarding no
ClientAliveInterval 15
ClientAliveCountMax 2
Le ClientAlive libère le port en environ 30 secondes si le serveur chiffré redémarre brutalement. Sans ça, l’ancien tunnel bloquerait le port et le nouveau ne pourrait pas s’ouvrir.
- Vérifier et recharger :
sshd -t && systemctl reload ssh
3. Créer la clé du tunnel (serveur chiffré)
- Générer une clé au format Dropbear :
dropbearkey -t ed25519 -f /etc/dropbear/initramfs/relay_key
dropbearkey -y -f /etc/dropbear/initramfs/relay_key | grep ^ssh-
- Sur le relais, ajouter la clé affichée dans
/home/tunnel/.ssh/authorized_keys, précédée des restrictions :
restrict,port-forwarding,permitlisten="10022" ssh-ed25519 AAAA...
Cette clé ne peut rien faire d’autre qu’ouvrir le port 10022 sur le relais.
Enregistrer l’empreinte du relais
Au démarrage, dbclient doit reconnaître le relais, sinon il veut demander une confirmation, et comme personne ne peut répondre, il abandonne.
- Lancer un premier test manuel et accepter l’empreinte avec
yes:
dbclient -N -i /etc/dropbear/initramfs/relay_key -p 2022 -R 10022:127.0.0.1:22 tunnel@relais.exemple.fr
- Pendant qu’il tourne, sur le relais :
ss -tlnp | grep 10022
Une ligne 127.0.0.1:10022 doit apparaître. Faire Ctrl+C sur le serveur chiffré.
- Copier l’empreinte enregistrée par
dbclient:
grep relais.exemple.fr /root/.ssh/known_hosts > /etc/dropbear/initramfs/relay_known_hosts
Attention : ne pas utiliser
ssh-keyscan. Il écrit[relais.exemple.fr]:2022 ...alors quedbclientchercherelais.exemple.fr ...: l’empreinte ne serait pas reconnue au démarrage.
4. Autoriser le relais à se connecter à Dropbear
- Sur le relais, récupérer (ou créer) la clé publique :
ls ~/.ssh/id_ed25519.pub || ssh-keygen -t ed25519
cat ~/.ssh/id_ed25519.pub
- Sur le serveur chiffré, l’ajouter sur une nouvelle ligne :
vim /etc/dropbear/initramfs/authorized_keys
5. Les scripts de l’initramfs (serveur chiffré)
- Créer les dossiers s’ils n’existent pas :
mkdir -p /etc/initramfs-tools/hooks \
/etc/initramfs-tools/scripts/init-premount \
/etc/initramfs-tools/scripts/init-bottom
Le hook
Il copie dbclient, la clé et l’empreinte dans l’initramfs au moment de sa construction.
vim /etc/initramfs-tools/hooks/reverse-tunnel
#!/bin/sh
PREREQ="dropbear"
prereqs() { echo "$PREREQ"; }
case "$1" in prereqs) prereqs; exit 0 ;; esac
. /usr/share/initramfs-tools/hook-functions
copy_exec /usr/bin/dbclient /bin
mkdir -p "${DESTDIR}/root/.ssh"
cp /etc/dropbear/initramfs/relay_key "${DESTDIR}/root/.ssh/relay_key"
cp /etc/dropbear/initramfs/relay_known_hosts "${DESTDIR}/root/.ssh/known_hosts"
chmod 700 "${DESTDIR}/root/.ssh"
chmod 600 "${DESTDIR}/root/.ssh/relay_key"
Le script qui ouvre le tunnel
Il s’exécute au démarrage, avant la demande du code.
vim /etc/initramfs-tools/scripts/init-premount/reverse-tunnel
#!/bin/sh
PREREQ="dropbear"
prereqs() { echo "$PREREQ"; }
case "$1" in prereqs) prereqs; exit 0 ;; esac
. /scripts/functions
RELAY_HOST="relais.exemple.fr"
RELAY_PORT="2022"
RELAY_USER="tunnel"
TUNNEL_PORT="10022"
configure_networking
ip link set lo up 2>/dev/null || ifconfig lo up 2>/dev/null
if [ ! -s /etc/resolv.conf ]; then
for f in /run/net-*.conf; do
[ -e "$f" ] && . "$f" && [ -n "$IPV4DNS0" ] && echo "nameserver $IPV4DNS0"
done > /etc/resolv.conf
[ -s /etc/resolv.conf ] || echo "nameserver 1.1.1.1" > /etc/resolv.conf
fi
(
export HOME=/root
while true; do
/bin/dbclient -N -K 30 -i /root/.ssh/relay_key -p "$RELAY_PORT" \
-R "${TUNNEL_PORT}:127.0.0.1:4748" "${RELAY_USER}@${RELAY_HOST}"
sleep 10
done
) >/dev/null 2>&1 &
echo $! > /run/reverse-tunnel.pid
Important : la ligne
ip link set lo upest indispensable. Dans l’initramfs, l’interface loopback n’est pas activée : sans elle,127.0.0.1n’existe pas et la connexion est coupée avecConnection reset by peer.
RELAY_HOSTdoit être écrit exactement comme dansrelay_known_hosts.- La boucle relance le tunnel toutes les 10 secondes s’il tombe.
- Pour débugger, remplacer
>/dev/nullpar>/dev/console: les erreurs s’affichent à l’écran au démarrage.
Le script qui coupe le tunnel
Il s’exécute une fois le disque déverrouillé.
vim /etc/initramfs-tools/scripts/init-bottom/reverse-tunnel
#!/bin/sh
PREREQ=""
prereqs() { echo "$PREREQ"; }
case "$1" in prereqs) prereqs; exit 0 ;; esac
[ -f /run/reverse-tunnel.pid ] && kill "$(cat /run/reverse-tunnel.pid)" 2>/dev/null
for p in $(pidof dbclient); do kill "$p" 2>/dev/null; done
exit 0
Rendre exécutable et reconstruire
chmod +x /etc/initramfs-tools/hooks/reverse-tunnel \
/etc/initramfs-tools/scripts/init-premount/reverse-tunnel \
/etc/initramfs-tools/scripts/init-bottom/reverse-tunnel
update-initramfs -u
Vérifier le contenu de l’initramfs
lsinitramfs /boot/initrd.img-$(uname -r) | grep -E 'dbclient|\.ssh|reverse-tunnel'
Il doit y avoir usr/bin/dbclient, root/.ssh/relay_key, root/.ssh/known_hosts et les deux scripts reverse-tunnel.
- Pour vérifier que les scripts intégrés sont bien complets :
rm -rf /tmp/initrd && unmkinitramfs /boot/initrd.img-$(uname -r) /tmp/initrd
cat $(find /tmp/initrd -path '*init-premount/reverse-tunnel')
6. Configurer le relais pour déverrouiller
Raccourci SSH
vim ~/.ssh/config
Host unlock
HostName localhost
Port 10022
User root
HostKeyAlias unlock-initramfs
StrictHostKeyChecking accept-new
ConnectTimeout 5
Le HostKeyAlias évite les conflits de clé avec les autres connexions à localhost.
Attendre le tunnel automatiquement
vim ~/.bashrc
unlock() {
echo "En attente du tunnel du nas..."
until ss -tln | grep -q ':10022 '; do sleep 2; done
echo "Tunnel prêt, connexion."
ssh unlock
}
source ~/.bashrc
7. Utilisation
- Redémarrer le serveur chiffré
- Sur le relais, lancer :
unlock
- Dès que le tunnel est monté, la demande du code s’affiche. Taper le code : la connexion se ferme et le serveur finit de démarrer.
Si un shell s’affiche au lieu de la demande du code, taper
cryptroot-unlock.
Dépannage
| Symptôme | Cause probable |
|---|---|
unlock attend indéfiniment |
Le tunnel ne se monte pas : vérifier relay_known_hosts, passer le script en >/dev/console et regarder l’écran au démarrage |
Connection reset by peer |
La loopback n’est pas activée (ip link set lo up manquant) ou Dropbear n’écoute pas sur 4748 |
Permission denied (publickey) |
La clé du relais n’est pas dans /etc/dropbear/initramfs/authorized_keys, ou update-initramfs -u n’a pas été relancé |
| Le port est déjà utilisé sur le relais | Choisir un port de tunnel différent du port SSH du relais |
- Suivre les connexions du tunnel sur le relais :
journalctl -u ssh -f | grep -i tunnel
À retenir : après toute modification de la clé, de l’empreinte, des scripts ou de
authorized_keys, relancerupdate-initramfs -u.