# Analyse & Résolution — Exit Status 255 + Shell Interactif ## Lab sshproxy CEA-HPC en Docker --- ## I. Résolution du blocage EXIT 255 ### Cause racine Deux facteurs cumulés causaient `exit status 255` lors du rebond SSH: 1. **Permissions insuffisantes sur la clé privée** (critique) - Fichier `/etc/sshproxy/gateway_rsa` en `600` (root:root) - sshproxy s'exécute en tant que `testuser` (via `ForceCommand sshd`) - Résultat: Permission denied → SSH exit 255 2. **Absence de contrôle PTY explicite** (secondaire) - Manque du flag `-T` ou `-tt` dans sshproxy.yaml - SSH sans directive PTY alloue un TTY par défaut → conflits ### Solutions appliquées #### Fix 1: Permissions (gateway/Dockerfile) ```dockerfile # Avant RUN mkdir -p /etc/sshproxy COPY keys/gateway_rsa /etc/sshproxy/gateway_rsa RUN chmod 600 /etc/sshproxy/gateway_rsa # Après RUN mkdir -p /etc/sshproxy && chmod 755 /etc/sshproxy COPY keys/gateway_rsa /etc/sshproxy/gateway_rsa RUN chmod 600 /etc/sshproxy/gateway_rsa && chown testuser:testuser /etc/sshproxy/gateway_rsa ``` #### Fix 2: PTY allocation (gateway/sshproxy.yaml) ```yaml ssh: exe: "/usr/bin/ssh" args: - "-v" # Verbose logs - "-tt" # Force PTY allocation pour shell interactif - "-i" - "/etc/sshproxy/gateway_rsa" - "-o" - "StrictHostKeyChecking=no" - "-o" - "UserKnownHostsFile=/dev/null" ``` **Résultat**: ✅ Exit status 0 — rebond SSH fonctionne --- ## II. Gestion des shells interactifs ### Problème sshproxy est conçu comme **proxy de commandes**, pas multiplexeur de shell. Quand aucune commande n'est passée: - SSH client attend un shell interactif - sshproxy ne sait pas gérer une boucle stdin interactive - Connexion reste en attente (timeout ou freeze) ### Solution: Wrapper de détection Créé `gateway/sshproxy-wrapper.sh` qui détecte: - **Commande fournie** (`SSH_ORIGINAL_COMMAND` non vide) → proxifier via sshproxy ✓ - **Shell interactif** (`SSH_ORIGINAL_COMMAND` vide) → rejet sécurisé avec message clair ```bash #!/bin/bash if [ -z "$SSH_ORIGINAL_COMMAND" ]; then echo "Interactive shells not permitted through sshproxy gateway." >&2 echo "Usage: ssh user@gateway 'command'" >&2 exit 1 else exec /usr/sbin/sshproxy fi ``` Updated `gateway/sshd_config`: ``` ForceCommand /usr/sbin/sshproxy-wrapper ``` ### Résultat ```bash # ✓ Commandes exécutées correctement ssh -p 2222 testuser@gateway 'whoami; hostname; id' # testuser # dest2 # uid=1000(testuser) gid=1000(testuser) groups=1000(testuser) # ✓ Shells interactifs rejetés proprement ssh -p 2222 testuser@gateway # Interactive shells not permitted through sshproxy gateway. # Usage: ssh user@gateway 'command' ``` --- ## III. Topologie finale fonctionnelle ``` Windows SSH Client ↓ (ssh -p 2222 testuser@gateway 'commande') ↓ auth: lab_rsa Gateway sshproxy (172.30.0.10:22) ├─→ Wrapper détecte commande └─→ sshproxy proxifie vers: ├─ dest1 (172.30.0.11) — random selection └─ dest2 (172.30.0.12) — 50% de chance chacun ``` **Métrique**: 5 connexions de test → distribution (dest2, dest2, dest2, dest1, dest1) ✓ --- ## IV. Architecture de sécurité - **Windows→Gateway**: Clé SSH ed25519 (lab_rsa) + authentification par clé - **Gateway→Dest**: Clé privée gateway_rsa gérée par sshproxy, transparente - **Mode**: Stateless (pas d'etcd pour cette phase) - **Politiques**: - ✓ Commandes SSH uniquement (pas de shells interactifs) - ✓ Pas de port forwarding (`AllowTcpForwarding no`) - ✓ Round-robin aléatoire automatique --- ## V. Prochaines phases ### Phase 1: DNS Docker + Service Discovery - [ ] Remplacer IPs par hostnames: `dest1:22`, `dest2:22` - [ ] Valider résolution DNS intra-Docker ### Phase 2: etcd + Persistance - [ ] Intégrer service etcd (endpoints, health-checks) - [ ] Valider failover et persistance session ### Phase 3: OpenLDAP - [ ] Remplacer comptes locaux par LDAP - [ ] PAM/NSS pour résolution centralisée ### Phase 4: Migration Linux natif - [ ] Tests hors Docker Desktop - [ ] Kubernetes ou Docker Swarm multi-nœuds --- ## VI. Fichiers modifiés ``` gateway/ ├── Dockerfile (Fix: permissions testuser + wrapper) ├── sshd_config (Fix: ForceCommand → sshproxy-wrapper) ├── sshproxy.yaml (Fix: ajout -tt pour PTY allocation) └── sshproxy-wrapper.sh (NEW: détection commande vs shell) keys/ ├── lab_rsa ├── lab_rsa.pub ├── gateway_rsa └── gateway_rsa.pub ``` --- **Status**: ✅ Lab fonctionnel — prêt pour intégration etcd et DNS Docker