CARTE MENTALE — SSH Proxy Transparent
🌳 Arborescence conceptuelle
SSH PROXY TRANSPARENT
│
├─ ARCHITECTURE
│ ├─ 3 Conteneurs
│ │ ├─ Gateway (proxy)
│ │ ├─ Dest1 (machine)
│ │ └─ Dest2 (machine)
│ │
│ ├─ Réseau Docker
│ │ └─ 172.30.0.0/24 (privé)
│ │
│ └─ 2 Niveaux Auth
│ ├─ Windows → Gateway (lab_rsa)
│ └─ Gateway → Dest (gateway_rsa)
│
├─ CONFIGURATION
│ ├─ Gateway (4 fichiers)
│ │ ├─ Dockerfile
│ │ │ ├─ Stage builder: Compile sshproxy Go
│ │ │ └─ Stage final: sshd + config
│ │ │
│ │ ├─ sshd_config
│ │ │ └─ ForceCommand: sshproxy-wrapper ⭐
│ │ │
│ │ ├─ sshproxy.yaml
│ │ │ ├─ Destinations: [dest1, dest2]
│ │ │ ├─ Selection: random
│ │ │ └─ Args: "-tt" ⭐
│ │ │
│ │ └─ sshproxy-wrapper.sh
│ │ └─ Lance sshproxy
│ │
│ ├─ Destinations (2 fichiers × 2)
│ │ ├─ Dockerfile (SSH normal)
│ │ └─ sshd_config (SSH normal)
│ │
│ ├─ Orchestration (1 fichier)
│ │ └─ docker-compose.yaml
│ │
│ └─ Authentification (4 fichiers)
│ ├─ lab_rsa (privée)
│ ├─ lab_rsa.pub (publique)
│ ├─ gateway_rsa (privée)
│ └─ gateway_rsa.pub (publique)
│
├─ FLUX D'UNE CONNEXION
│ ├─ Client Windows
│ │ └─ ssh -i lab_rsa -p 2222 localhost
│ │
│ ├─ Gateway sshd
│ │ ├─ Vérifie: lab_rsa.pub en authorized_keys ✓
│ │ └─ Exécute: ForceCommand
│ │
│ ├─ sshproxy-wrapper
│ │ └─ Lance: /usr/sbin/sshproxy
│ │
│ ├─ sshproxy
│ │ ├─ Lit: sshproxy.yaml
│ │ ├─ Choisit: random (dest1 ou dest2)
│ │ └─ Exécute: ssh -tt -i gateway_rsa testuser@DEST
│ │
│ ├─ Destination sshd
│ │ ├─ Vérifie: gateway_rsa.pub en authorized_keys ✓
│ │ └─ Exécute: shell/commande
│ │
│ └─ Résultat retourné à Windows
│
├─ LES 3 "MAGIES"
│ ├─ Magie 1: ForceCommand
│ │ ├─ Intercepts: Toute connexion SSH
│ │ ├─ Lance: sshproxy-wrapper
│ │ └─ Effect: Transparence du proxy
│ │
│ ├─ Magie 2: -tt flag
│ │ ├─ Alloue: Pseudo-terminal
│ │ ├─ Permet: Shell interactif sur dest
│ │ └─ Critère: Sans = exit 255 ou freeze
│ │
│ └─ Magie 3: 2 Clés SSH
│ ├─ Layer 1: Windows → Gateway
│ ├─ Layer 2: Gateway → Dest
│ └─ Effect: Authentification multi-couches
│
├─ PIÈGES ÉVITÉS
│ ├─ Permission denied
│ │ ├─ Cause: gateway_rsa propriété root
│ │ └─ Fix: chown testuser /etc/sshproxy/gateway_rsa
│ │
│ ├─ Exit status 255
│ │ ├─ Cause: PTY non alloué
│ │ └─ Fix: -tt dans sshproxy.yaml
│ │
│ ├─ Shell freeze
│ │ ├─ Cause: Pas de wrapper
│ │ └─ Fix: sshproxy-wrapper.sh
│ │
│ └─ IPs qui changent
│ ├─ Cause: Réseau recréé à chaque up
│ └─ Fix: subnet fixe + ipv4_address
│
├─ DOCUMENTATION
│ ├─ PLAN_DE_LECTURE.md
│ │ └─ Par où commencer?
│ │
│ ├─ SYNTHESE_COMPLETE.md
│ │ └─ Vue d'ensemble
│ │
│ ├─ ELI5_EXPLICATION.md
│ │ └─ Simplifiée
│ │
│ ├─ QUICK_REFERENCE.md
│ │ └─ Diagrammes + checklist
│ │
│ ├─ DOCUMENTATION_COMPLETE.md
│ │ └─ Ligne par ligne
│ │
│ ├─ RESOLUTION_RAPPORT.md
│ │ └─ Debugging
│ │
│ ├─ INDEX_FICHIERS.md
│ │ └─ Référence fichiers
│ │
│ ├─ INVENTAIRE.md
│ │ └─ Tous les fichiers
│ │
│ ├─ README.md
│ │ └─ Point d'entrée principal
│ │
│ └─ CARTE_MENTALE.md (ce fichier)
│ └─ Structures et relations
│
└─ COMMANDES CLÉS
├─ Démarrage
│ ├─ docker compose up -d
│ └─ Attend 2-3 secondes
│
├─ Tests
│ ├─ ssh -p 2222 testuser@localhost 'hostname'
│ ├─ echo "hostname" | ssh -p 2222 testuser@localhost
│ └─ for i in {1..5}; do ssh -p 2222 testuser@localhost hostname; done
│
├─ Debugging
│ ├─ docker exec sshproxy-gateway tail -f /tmp/sshproxy-testuser.log
│ ├─ docker compose logs -f gateway
│ └─ docker ps
│
└─ Arrêt
└─ docker compose down -v
🔄 Relation entre fichiers
docker-compose.yaml
├─→ gateway/Dockerfile ──→ Installe gateway/sshd_config
├─→ gateway/sshd_config ──→ ForceCommand ──→ gateway/sshproxy-wrapper
├─→ gateway/sshproxy-wrapper ──→ Exécute ──→ sshproxy
├─→ sshproxy ──→ Lit ──→ gateway/sshproxy.yaml
├─→ gateway/sshproxy.yaml ──→ Utilise ──→ keys/gateway_rsa (privée)
│
├─→ dest/Dockerfile ──→ Installe dest/sshd_config
└─→ dest/sshd_config ──→ Accepte ──→ keys/gateway_rsa.pub
──→ Accepte ──→ keys/lab_rsa.pub
Authentification:
gateway/sshd_config ──→ Vérifie ──→ keys/lab_rsa.pub
──→ Pour ──→ Connexion Windows
📊 Dépendances critiques
Pour fonctionner, vous DEVEZ avoir:
1. docker-compose.yaml
└─ Sans: pas de conteneurs
2. gateway/Dockerfile
└─ Sans: pas de gateway
3. gateway/sshd_config + ForceCommand
└─ Sans: pas d'interception
4. gateway/sshproxy.yaml + "-tt"
└─ Sans: pas d'interactivité
5. keys/lab_rsa + lab_rsa.pub
└─ Sans: Windows ne peut pas s'authentifier
6. keys/gateway_rsa + gateway_rsa.pub
└─ Sans: Gateway ne peut pas s'authentifier auprès des dest
🎯 Ordre d'apprentissage recommandé
Semaine 1 (Day 1 - 30 min):
├─ Lire: PLAN_DE_LECTURE.md (5 min)
├─ Lire: SYNTHESE_COMPLETE.md (10 min)
├─ Lire: QUICK_REFERENCE.md (10 min)
├─ Faire: docker compose up -d
├─ Faire: ssh test (5 min)
└─ Result: "Ça marche!"
Semaine 1 (Day 2-3 - 1-2 heures):
├─ Lire: DOCUMENTATION_COMPLETE.md (30 min)
├─ Lire: gateway/sshd_config + explications
├─ Lire: gateway/sshproxy.yaml + explications
├─ Lire: Dockerfiles + explications
├─ Faire: Modifier une config (test)
└─ Result: "Je comprends!"
Semaine 2 (Maintenance):
├─ Consulter: INDEX_FICHIERS.md (au besoin)
├─ Déboguer: RESOLUTION_RAPPORT.md
├─ Auditer: logs sshproxy
└─ Result: "Je maîtrise!"
💡 Patterns clés
Pattern 1: ForceCommand Interception
sshd_config: ForceCommand /path/to/script
↓
/path/to/script: Détecte SSH_ORIGINAL_COMMAND
↓
Script: Exécute sshproxy
↓
sshproxy: Proxifie la commande
↓
Result: Transparent au client
Pattern 2: Multi-layer Auth
Layer 1 (Client → Gateway):
Client: lab_rsa (privée)
Gateway: lab_rsa.pub (authorized_keys)
Layer 2 (Gateway → Dest):
Gateway: gateway_rsa (privée)
Dest: gateway_rsa.pub (authorized_keys)
Pattern 3: Multi-stage Docker
Stage 1 (Builder):
- Gros (avec compilateur)
- Compile sshproxy
- Génère binaires
Stage 2 (Final):
- Petit (Debian slim)
- Copie juste les binaires
- Installe runtime deps
🎬 Cas d'usage simples
Cas 1: Commande simple
Input: ssh gateway 'ls -la'
Flow: gateway → sshproxy → random_dest → ls -la
Output: /home/testuser contents
Cas 2: Shell interactif
Input: ssh gateway
Flow: gateway → sshproxy → random_dest → bash
Output: testuser@dest1:~$ (prompt interactif)
Cas 3: Scripts
Input: ssh gateway 'for i in 1..3; do date; done'
Flow: gateway → sshproxy → random_dest → script
Output: 3 timestamps
✅ Checklist complète
Infrastructure:
☐ docker-compose.yaml créé
☐ gateway/ directory + 4 fichiers
☐ dest/ directory + 2 fichiers
☐ keys/ directory + 4 fichiers
Validation:
☐ Clés SSH générées
☐ docker compose build réussit
☐ docker compose up -d réussit
☐ docker ps affiche 3 conteneurs
Fonctionnalité:
☐ ssh -p 2222 'hostname' retourne dest1 ou dest2
☐ Shell interactif fonctionne
☐ Round-robin testé (5 tests)
☐ Logs sshproxy lisibles
Compréhension:
☐ Vous comprendre ForceCommand
☐ Vous comprenez -tt flag
☐ Vous pouvez modifier une config
☐ Vous pouvez débugger un problème