ADR-074 — Vision air-sshd : démon SSH natif d’Air, wire-compatible OpenSSH mais pas opensshd (async io_uring, conf binaire, profil algorithmique moderne)
Statut : Accepté (2026-07-07, décision BDFL directe — vision cadrante ; le détail d’implémentation viendra par sous-ADR/RFC au fil des phases). S’appuie sur la Charte, les Principes d’ingénierie, le périmètre de connectivité tier-1 (ssh), et ADR-073 (configuration binaire). Consomme le socle réseau couche 1 d’ADR-069.
Catégorie : Vision d’un composant (couche 2+). Cadre un objectif majeur ; n’altère aucune couche scellée.
Contexte — pourquoi ne pas simplement porter OpenSSH
L’objectif intermédiaire « compiler OpenSSH sur Air » a été une fonction de forçage :
il a servi à révéler et prioriser ce qui manquait fonctionnellement en couche 1 pour
un vrai démon réseau (registre de handles, moteur socket, poll/select, résolution de
noms). Cet objectif est atteint — mais porter OpenSSH n’est pas la fin visée.
OpenSSH, tel qu’implémenté, présente des défauts que la posture Air veut éliminer :
- Sa configuration est en texte clair (
~/.ssh/config,sshd_config) — surface d’attaque directe (cf. le modèle de menace d’ADR-073 : lecture/modification triviale par un shell compromis, réécriture de la conf du démon soussudopermissif). - Sa base de code C historique porte tout un héritage d’algorithmes legacy (RSA-sha1,
diffie-hellman-group1, modes CBC, etc.) que la charte Air veut ne pas faire cohabiter avec le moderne. - Le porter impliquerait la façade libc C et une
libcryptoC-ABI — coûteux, et orthogonal à l’objectif.
Décision
Air fournit son propre démon SSH, air-sshd : compatible OpenSSH « on the wire »
(protocole SSH-2, RFC 4251-4254, de sorte qu’un client ssh standard s’y connecte)
mais PAS opensshd — une réimplémentation from-scratch en Rust, avec quatre partis
pris :
-
Asynchrone, sur le socle Air.
air-sshdest bâti sur la runloop + io_uring d’Air (couche 0 Temps 2b réseau) et le socle couche 1 (air-socket/air-handle/air-poll/air-runtime). Pas de thread-par-connexion bloquant : boucle d’événements. -
Configuration binaire (ADR-073).
air-sshdlit sa configuration depuis un fichier binaire, manipulé par un CLI dédié sous ré-authentification administrateur. La compatibilitésshd_configtexte, si fournie, passe par import/export — jamais par une conf texte vivante. -
Crypto native Rust, directe.
air-sshdutilise l’API Rust d’air-cryptodirectement — aucunelibcryptoC-ABI, aucune façade libc. Le socle crypto est celui d’Air, sûr et audité côté Rust. -
Profil algorithmique moderne UNIQUEMENT — sûr par construction.
air-sshdn’annonce et n’accepte que les algorithmes modernes, et refuse explicitement le legacy (pas de RSA-sha1, pas dediffie-hellman-group1, pas de CBC-EtM). Cible initiale, entièrement couverte parair-cryptoaujourd’hui :- KEX :
curve25519-sha256(X25519 + SHA-256). - Clé d’hôte / signature :
ssh-ed25519(Ed25519). - Chiffrement authentifié :
chacha20-poly1305@openssh.cometaes256-gcm@openssh.com. - MAC (pour les modes non-AEAD) :
hmac-sha2-256/512.
Le support RSA / ECDSA-NIST / DH-group est une extension de compatibilité client éventuelle et assumée comme non-souhaitée — pas un prérequis. « Le propre et le legacy ne cohabitent pas » (Charte).
- KEX :
Conséquences
air-sshdn’a besoin ni de la façade libc C ni d’unelibcryptoC-ABI. Ces deux chantiers (les 55 manques libc, les ~120 symboles libcrypto révélés par la sonde OpenSSH) appartiennent à la piste distincte « compiler du C contre Air / clang air » et sont différés — ils ne sont pas sur le chemin critique d’air-sshd.- Le socle réseau couche 1 (ADR-069) est exactement ce que
air-sshdconsomme — le travail de la campagne réseau reste pleinement investi. Les shims socket libc restent un sous-produit utile à la piste C-toolchain. - Compatibilité = « on the wire », pas la conf. Un client
sshmoderne se connecte àair-sshd; en revanche la configuration est propriétaire/binaire (non compatiblesshd_config, mais importable/exportable — ADR-073). C’est un choix de sécurité assumé. - Découpage en phases (chacune un sous-ADR/RFC + jalon) :
- Couche transport SSH-2 : échange d’identification (
SSH-2.0-…),KEXINIT(négociation, n’annonçant que le moderne), KEXcurve25519-sha256, dérivation de clés, protocole de paquets binaire chiffré (ChaCha20-Poly1305), le tout async. ssh-userauth: authentificationpublickeyEd25519 d’abord.ssh-connection: canaux,pty-req/shell/exec, redirections.
- Couche transport SSH-2 : échange d’identification (
- Provenance d’exécution :
air-sshds’inscrit dans la doctrine « exécution par provenance » d’Air (le shell servi, les binaires lancés) — à articuler au fil des phases.
Alternatives rejetées
- Porter/compiler OpenSSH : conserve la surface d’attaque de la conf texte, tire la
dépendance C +
libcrypto, et impose l’héritage algorithmique legacy. C’était une fonction de forçage, pas la cible. - Enrober opensshd (wrapper) : reste opensshd, avec ses partis pris de conception.
- Supporter les algorithmes legacy pour une compat client maximale : affaiblit la posture de sécurité ; contraire à la Charte. La compat legacy, si un jour nécessaire, sera un ajout explicite et délimité, jamais le défaut.