03_ARCHITECTURE_DIAGRAMMES.md 11 KB

Quick Reference — Architecture du proxy SSH transparent

📐 Architecture Visuelle

┌─────────────────────────────────────────────────────────────────┐
│ WINDOWS CLIENT (ssh -p 2222 -i lab_rsa testuser@localhost)     │
└────────────────────────┬────────────────────────────────────────┘
                         │
                         │ Port 2222 (remappé vers 172.30.0.10:22)
                         │ Clé: lab_rsa
                         ↓
┌─────────────────────────────────────────────────────────────────┐
│ GATEWAY (172.30.0.10:22)                                        │
│ ┌──────────────────────────────────────────────────────────┐   │
│ │ SSH Daemon (sshd)                                        │   │
│ │ - Accepte clé lab_rsa.pub                                │   │
│ │ - Exécute: ForceCommand /usr/sbin/sshproxy-wrapper      │   │
│ └──────────────────────────────────────────────────────────┘   │
│ ┌──────────────────────────────────────────────────────────┐   │
│ │ sshproxy-wrapper.sh                                      │   │
│ │ - Détecte commande vs shell                              │   │
│ │ - Lance: /usr/sbin/sshproxy                              │   │
│ └──────────────────────────────────────────────────────────┘   │
│ ┌──────────────────────────────────────────────────────────┐   │
│ │ sshproxy (daemon compilé en Go)                          │   │
│ │ - Lit config: sshproxy.yaml                              │   │
│ │ - Choisit destination: random(dest1, dest2)              │   │
│ │ - Exécute rebond SSH avec clé gateway_rsa                │   │
│ └──────────────────────────────────────────────────────────┘   │
└────────────────┬────────────────────────────────────────────────┘
                 │
        ┌────────┴────────┐
        │ random()        │
        ↓ 50%             ↓ 50%
┌───────────────────┐    ┌───────────────────┐
│ DEST1             │    │ DEST2             │
│ 172.30.0.11:22    │    │ 172.30.0.12:22    │
│                   │    │                   │
│ SSH Daemon        │    │ SSH Daemon        │
│ - Accepte         │    │ - Accepte         │
│   gateway_rsa.pub │    │   gateway_rsa.pub │
│ - Shell normal    │    │ - Shell normal    │
└───────────────────┘    └───────────────────┘

🔑 Authentification à 2 niveaux

AUTHENTIFICATION NIVEAU 1: Windows → Gateway
┌─────────────────────────────────┐
│ Client Windows                  │
│ Clé privée: lab_rsa             │
│ Clé publique: lab_rsa.pub       │
└────────────┬────────────────────┘
             │
             ↓
┌─────────────────────────────────┐
│ Gateway /home/testuser/.ssh/    │
│ authorized_keys (contient)      │
│ → lab_rsa.pub                   │
└─────────────────────────────────┘
✓ Connexion Windows→Gateway autorisée


AUTHENTIFICATION NIVEAU 2: Gateway → Destinations
┌─────────────────────────────────┐
│ Gateway /etc/sshproxy/          │
│ Clé privée: gateway_rsa         │
│ Clé publique: gateway_rsa.pub   │
└────────────┬────────────────────┘
             │
             ↓ (utilisée par sshproxy)
┌─────────────────────────────────┐
│ Dest1/Dest2 /home/testuser/.ssh/│
│ authorized_keys (contient)      │
│ → gateway_rsa.pub               │
└─────────────────────────────────┘
✓ Connexion Gateway→Destinations autorisée

📝 Fichiers clés et leurs rôles

INFRASTRUCTURE

  • docker-compose.yaml: Définit 3 conteneurs + réseau privé

GATEWAY

  • gateway/Dockerfile:
    • Build sshproxy v2.1.0 en Go
    • Installe sshd
    • Configure comptes + permissions
  • gateway/sshd_config:
    • ForceCommand /usr/sbin/sshproxy-wrapper ← Clé!
    • Auth par clé uniquement
  • gateway/sshproxy.yaml:
    • Destinations: 172.30.0.11, 172.30.0.12
    • Selection: random
    • SSH args: -tt (PTY) crucial
  • gateway/sshproxy-wrapper.sh:
    • Détecte shell interactif vs commande
    • Exécute sshproxy dans les deux cas

DESTINATIONS

  • dest/Dockerfile:
    • Installe sshd uniquement
    • Pas de sshproxy (pas besoin)
  • dest/sshd_config:
    • SSH normal (pas de ForceCommand)
    • Auth par clé (gateway_rsa.pub)

AUTHENTIFICATION

  • keys/lab_rsa: Privée Windows (utilisateur garde secret)
  • keys/lab_rsa.pub: Publique → authorized_keys gateway
  • keys/gateway_rsa: Privée gateway (compilée dans image)
  • keys/gateway_rsa.pub: Publique → authorized_keys dest1/dest2

🔄 Processus d'une connexion

CLIENT WINDOWS
│
├─ ssh -p 2222 -i lab_rsa testuser@localhost 'hostname'
│  (ou sans 'hostname' pour shell interactif)
│
└─→ GATEWAY sshd (port 2222)
   │
   ├─ Vérifie: lab_rsa.pub en authorized_keys? ✓
   ├─ Lance: /usr/sbin/sshproxy-wrapper
   │
   └─→ SSHPROXY-WRAPPER
      │
      ├─ Détecte: $SSH_ORIGINAL_COMMAND fournie?
      │  (oui/non, peu importe → fait pareil)
      │
      └─→ /usr/sbin/sshproxy (daemon Go)
         │
         ├─ Lit: /etc/sshproxy/sshproxy.yaml
         ├─ Choisit: random → 172.30.0.11 ou 172.30.0.12
         │
         └─→ Exécute: ssh -tt -i /etc/sshproxy/gateway_rsa testuser@DESTINATION 'hostname'
            │
            ├─ Vérifie: gateway_rsa en authorized_keys? ✓
            │
            └─→ DESTINATION sshd (normal)
               │
               └─ Exécute: 'hostname'
                  Retourne résultat à client

⚙️ Configuration minimale requise

Clés SSH (pré-générées)

# Générer si manquantes:
ssh-keygen -t ed25519 -f keys/lab_rsa -N ""        # Windows→Gateway
ssh-keygen -t ed25519 -f keys/gateway_rsa -N ""    # Gateway→Dest

Structure minimale

.
├── docker-compose.yaml
├── keys/
│   ├── lab_rsa                    # ← Windows garde privé
│   ├── lab_rsa.pub               # ← Copié dans gateway
│   ├── gateway_rsa                # ← Compilation dans image
│   └── gateway_rsa.pub            # ← Copié dans destinations
├── gateway/
│   ├── Dockerfile
│   ├── sshd_config                # ← ForceCommand crucial
│   ├── sshproxy.yaml              # ← -tt crucial
│   └── sshproxy-wrapper.sh
└── dest/
    ├── Dockerfile
    └── sshd_config

🚀 Commandes de test

# Lancer l'infrastructure
docker compose up -d

# Test 1: Commande simple
ssh -p 2222 -i keys/lab_rsa testuser@localhost 'hostname'
# Résultat: dest1 ou dest2 (random)

# Test 2: Commande avec sortie
ssh -p 2222 -i keys/lab_rsa testuser@localhost 'whoami; pwd; id'
# Résultat: testuser, /home/testuser, uid=1000...

# Test 3: Shell interactif (piped)
echo "hostname" | ssh -p 2222 -i keys/lab_rsa testuser@localhost
# Résultat: testuser@dest1:~$ hostname ↵ dest1

# Test 4: Vérifier round-robin
for i in {1..5}; do ssh -p 2222 -i keys/lab_rsa testuser@localhost hostname; done
# Résultat: dest2, dest1, dest2, dest1, dest2 (alternance aléatoire)

# Test 5: Voir les logs sshproxy
docker exec sshproxy-gateway tail -f /tmp/sshproxy-testuser.log

# Vérifier structure réseau
docker network inspect sshproxy_net

# Arrêter
docker compose down -v

🎯 Ce qui rend le proxy transparent

Élément Raison
ForceCommand Intercepte SSH → proxifie
sshproxy wrapper Gère shell et commandes uniformément
-tt flag PTY allocation pour interactivité
gateway_rsa Identité gateway pour rebond auto
Random route_select Répartition charge automatique
IPs Docker fixes Destinations prévisibles pour sshproxy

🔍 Cas d'usage

✅ Fonctionne

ssh gateway 'ls -la'                    # Commandes
ssh gateway 'for i in 1..3; do date; done'  # Scripts
ssh gateway                             # Shell interactif
ssh gateway 'bash'                      # Lancer shell explicite

❌ Ne fonctionne pas (intentionnel)

ssh gateway -L 3306:dest:3306           # Port forwarding (AllowTcpForwarding no)
ssh gateway -X                          # X11 forwarding (X11Forwarding no)

📊 Statistiques architecture

  • Gateway: 1 conteneur (proxy + orchestration)
  • Destinations: 2 conteneurs (SSH normal)
  • Réseau: Bridge Docker privé (172.30.0.0/24)
  • Port exposé: 2222 (remappé vers port 22 gateway)
  • Auth: 2 niveaux (client→gateway + gateway→dest)
  • Sélection: Random (50/50 dest1 vs dest2)