← Accueil

PCTAMALOU

Semaine 7 : Les Portes de la Cité – Ports, Protocoles TCP/UDP et Handshake

Par Platon-Y – pctamalou.fr & e-of-h.fr

🎯 Objectif de la semaine

Maîtriser les ports réseau, les protocoles TCP/UDP et le handshake TCP pour comprendre comment les applications communiquent sur le réseau, identifier les services exposés et détecter les connexions suspectes en temps réel.

Pourquoi c'est critique : Chaque port ouvert est une porte potentielle pour un attaquant. Savoir quels ports sont ouverts, ce qu'ils font et qui y accède, c'est contrôler les entrées de votre cité numérique.

flowchart TD A[🌐 IP: 192.168.1.100] --> B{PORTS: 0-65535} B --> C[🔒 0-1023
Well-Known
Réservés système] B --> D[🔐 1024-49151
Registered
Applications] B --> E[🔓 49152-65535
Éphémères
Clients] C --> F[📡 Services:
22 SSH, 80 HTTP
443 HTTPS, 53 DNS] D --> G[💼 Applications:
3306 MySQL, 5432 PostgreSQL
8080 HTTP Alt] E --> H[👤 Connexions clients
Sortantes temporaires] I[🔄 TCP] --> J[🤝 Handshake 3-way
SYN → SYN-ACK → ACK] I --> K[📊 Connecté
Fiabilité, séquencement
HTTP, SSH, SMTP] L[⚡ UDP] --> M[🎯 Sans connexion
Pas de handshake] L --> N[🚀 Rapide, léger
DNS, DHCP, Streaming
VoIP, Jeux] O[🎭 État TCP] --> P[LISTEN
Port ouvert, en attente] O --> Q[ESTABLISHED
Connexion active] O --> R[SYN_SENT
Demande envoyée] O --> S[TIME_WAIT
Fermeture propre] style C fill:#0a0e17,stroke:#00d4ff,stroke-width:2px style I fill:#11151f,stroke:#9d4edd,stroke-width:2px style P fill:#00f5a0,stroke:#000,stroke-width:2px

📚 Sujet – Théorie (1 heure)

Les ports : les adresses des applications

🏠 Analogie immobilière :

Une adresse IP = une maison
Un port = une pièce dans cette maison
Un service = ce qui se passe dans la pièce

Exemple : 192.168.1.100:443
• Maison : 192.168.1.100
• Pièce : 443 (salle des coffres sécurisée)
• Service : HTTPS (conversations chiffrées)

Les trois catégories de ports

Plage Nom Qui les utilise Permissions requises Exemples courants Risque sécurité
0-1023 Well-Known Système, services essentiels root/sudo 22(SSH), 80(HTTP), 443(HTTPS) 🔴 Élevé si exposé
1024-49151 Registered Applications utilisateur User standard 3306(MySQL), 8080(HTTP Alt) 🟡 Moyen
49152-65535 Éphémères/Dynamiques Clients, connexions sortantes N'importe quel processus Ports temporaires 🟢 Faible

TCP vs UDP : Le match des protocoles

flowchart LR subgraph TCP[Transmission Control Protocol] direction TB A[SYN] --> B[SYN-ACK] --> C[ACK] D[📦 Données séquencées] --> E[✅ Accusés réception] F[🔄 Retransmission si perte] --> G[🔒 Fermeture propre] end subgraph UDP[User Datagram Protocol] direction TB H[🎯 Envoi direct] --> I[⚡ Pas d'accusé] J[🚀 Rapide, léger] --> K[📉 Tolérance perte] L[🎵 Streaming, jeux] --> M[🔓 Pas de connexion] end TCP --> N[📨 Applications critiques
Web, mail, fichiers] UDP --> O[🎭 Applications temps réel
VoIP, DNS, vidéo] style TCP fill:#11151f,stroke:#00d4ff,stroke-width:2px style UDP fill:#0a0e17,stroke:#9d4edd,stroke-width:2px

Le handshake TCP en 3 étapes : La poignée de main numérique

🤝 Détail du handshake TCP :

Client (192.168.1.100:54321)          Serveur (93.184.216.34:80)
        |                                       |
        |---------- SYN seq=100 --------------->|
        |                                       | (État: SYN_RECEIVED)
        |<--------- SYN-ACK seq=300, ack=101----|
        |                                       |
        |---------- ACK seq=101, ack=301------->|
        |                                       | (État: ESTABLISHED)
        |           Connexion établie           |

Chaque étape contient :

  • SYN : "Je veux parler, mon numéro de séquence commence à 100"
  • SYN-ACK : "OK, parlons. Mon numéro commence à 300, j'ai reçu ton 101"
  • ACK : "Parfait, j'ai reçu ton 301"

Les états TCP : Le langage des connexions

⚠️ Les états TCP révélateurs :

  • LISTEN : Port ouvert, en attente de connexions → Service actif
  • SYN_SENT : Client a envoyé SYN, attend réponse → Scan en cours
  • SYN_RECEIVED : Serveur a reçu SYN, a répondu SYN-ACK → Attente finalisation
  • ESTABLISHED : Connexion active, échange de données → Communication normale
  • FIN_WAIT : Début de fermeture propre → Fin normale
  • CLOSE_WAIT : Attente fermeture par l'application → Possible fuite socket
  • TIME_WAIT : Attente avant libération complète → Évite paquets errants

Ports ouverts = surface d'attaque

🔓 Les 5 ports les plus dangereux à exposer :

  1. Port 22 (SSH) : Bruteforce constant, mauvaises configurations
  2. Port 3389 (RDP) : Cible privilégiée des ransomwares
  3. Port 445 (SMB) : EternalBlue, partages non sécurisés
  4. Port 21 (FTP) : Authentification en clair, exploits anciens
  5. Port 23 (Telnet) : Tout en clair, obsolète et dangereux

Règle du Gardien : "Si tu n'as pas besoin d'un port, ferme-le. Si tu l'ouvres, surveille-le."

Les outils de visualisation : ss vs netstat

# ss (socket statistics) - Moderne, rapide
ss -tulnp                    # -t: TCP, -u: UDP, -l: listening, -n: numeric, -p: process

# netstat (network statistics) - Classique, plus d'options
netstat -tunlp               # Même chose mais plus lent

# Comparaison des colonnes importantes:
État        Signification
--------    -------------
LISTEN      En attente de connexions
ESTABLISHED Connexion active
SYN_SENT    Client essaie de se connecter
TIME_WAIT   Fermeture en cours

💡 Philosophie du monitoring réseau :

"Ne surveille pas seulement ce qui entre et sort. Surveille surtout ce qui écoute."

Un port en écoute est une promesse : "Je suis prêt à accepter des connexions." Assurez-vous que cette promesse ne soit pas une menace.

🔬 Mission pratique – Laboratoire (2 heures)

Scénario : Audit de sécurité d'un serveur exposé

Vous êtes chargé d'analyser un serveur Linux exposé sur Internet. Votre mission : identifier tous les ports ouverts, les services associés, et évaluer les risques.

📝 Préparation : Installez les outils nécessaires.

sudo apt update
sudo apt install -y net-tools lsof nmap tcpdump telnet
# net-tools: netstat
# lsof: liste des fichiers ouverts (dont sockets)
# nmap: scanner de ports (semaine suivante)
# tcpdump: analyseur de paquets
# telnet: client TCP simple

Étapes détaillées : Analyse complète

  1. Analyse des ports en écoute (Listening)
    Commencez par comprendre ce qui écoute sur votre machine :
    echo "=== PORTS EN ÉCOUTE (ss) ==="
    sudo ss -tulnp
    
    echo -e "\n=== ANALYSE DÉTAILLÉE ==="
    # Par protocole
    echo "TCP en écoute:"
    sudo ss -tlnp
    
    echo -e "\nUDP en écoute:"
    sudo ss -ulnp
    
    # Alternative avec netstat
    echo -e "\n=== AVEC NETSTAT (alternative) ==="
    sudo netstat -tulnp
    
    # Sauvegarde pour analyse
    sudo ss -tulnp > ports_listening.txt
    echo "Rapport sauvegardé dans ports_listening.txt"
  2. Analyse des connexions actives
    Identifiez ce qui communique actuellement :
    echo "=== CONNEXIONS ACTIVES ==="
    sudo ss -tunap
    
    echo -e "\n=== FILTRES PAR ÉTAT ==="
    echo "Connexions établies:"
    sudo ss -tan state established
    
    echo -e "\nConnexions en attente:"
    sudo ss -tan state listening
    
    echo -e "\nToutes les connexions TCP:"
    sudo ss -tan
    
    # Analyse des états TCP
    echo -e "\n=== RÉPARTITION DES ÉTATS TCP ==="
    sudo ss -tan | awk '{print $1}' | sort | uniq -c | sort -rn
    
    # Connexions sortantes vs entrantes
    echo -e "\n=== CONNEXIONS SORTANTES (source port > 49151) ==="
    sudo ss -tan state established | awk '$5 ~ /:[0-9]+$/ {split($5,a,":"); if(a[2] > 49151) print}' | head -10
  3. Analyse avec lsof (List Open Files)
    Alternative puissante pour voir les sockets ouverts :
    echo "=== ANALYSE AVEC LSOF ==="
    sudo lsof -i
    
    echo -e "\n=== PORTS EN ÉCOUTE AVEC PROCESSUS ==="
    sudo lsof -i -s TCP:LISTEN
    
    echo -e "\n=== CONNEXIONS TCP ÉTABLIES ==="
    sudo lsof -i -s TCP:ESTABLISHED
    
    echo -e "\n=== PAR PORT SPÉCIFIQUE ==="
    sudo lsof -i :22  # SSH
    sudo lsof -i :80  # HTTP
    sudo lsof -i :443 # HTTPS
    
    # Format détaillé
    sudo lsof -Pan -i tcp -i udp
  4. Observation d'un handshake TCP en direct
    Créez et observez une connexion TCP :
    # Dans le terminal 1 : Observation
    echo "Terminal 1 - Observation:"
    echo "Ouvrez un autre terminal pour l'étape 2"
    sudo tcpdump -i any -n "tcp port 80" &
    TCPDUMP_PID=$!
    
    # Dans le terminal 2 (ouvrez-en un nouveau) : Connexion
    echo "Terminal 2 - Connexion:"
    echo "Lancez cette commande dans un nouveau terminal:"
    echo "telnet httpbin.org 80"
    echo "Puis tapez: GET /html HTTP/1.1"
    echo "Puis tapez: Host: httpbin.org"
    echo "Puis appuyez deux fois sur Entrée"
    
    read -p "Appuyez sur Entrée quand c'est fait dans l'autre terminal..."
    
    # Nettoyage
    sudo kill $TCPDUMP_PID 2>/dev/null
    
    # Analyse des états pendant la connexion
    echo -e "\n=== ÉTATS PENDANT CONNEXION ==="
    sudo ss -tan state established | grep :80
  5. Script Python d'analyse automatique
    Créez un outil d'audit professionnel :
    #!/usr/bin/env python3
    """
    PCTAMALOU - Semaine 7 : Analyseur de ports et connexions
    Outils pour auditer les ports ouverts et les connexions actives
    """
    
    import subprocess
    import json
    import re
    from datetime import datetime
    from collections import defaultdict, Counter
    
    def run_command(cmd):
        """Exécute une commande et retourne la sortie"""
        try:
            result = subprocess.run(cmd, shell=True, capture_output=True, text=True, check=True)
            return result.stdout
        except subprocess.CalledProcessError as e:
            return f"Erreur: {e}"
    
    def parse_ss_output(output):
        """Parse la sortie de ss -tulnp"""
        lines = output.strip().split('\n')
        listening_ports = []
        
        for line in lines[1:]:  # Skip header
            if not line.strip():
                continue
            
            # Format: Netid State  Recv-Q Send-Q Local Address:Port Peer Address:Port Process
            parts = line.split()
            if len(parts) >= 6:
                try:
                    netid = parts[0]
                    state = parts[1]
                    local = parts[4]
                    peer = parts[5]
                    process = ' '.join(parts[6:]) if len(parts) > 6 else ''
                    
                    # Extraction du port
                    port_match = re.search(r':(\d+)$', local)
                    if port_match:
                        port = int(port_match.group(1))
                        
                        # Extraction IP
                        ip_match = re.match(r'([^:]+):', local)
                        ip = ip_match.group(1) if ip_match else '*'
                        
                        listening_ports.append({
                            'protocol': 'TCP' if 'tcp' in netid.lower() else 'UDP',
                            'state': state,
                            'ip': ip,
                            'port': port,
                            'process': process,
                            'full_line': line
                        })
                except (IndexError, ValueError):
                    continue
        
        return listening_ports
    
    def analyze_ports(ports):
        """Analyse les ports pour détecter les risques"""
        risks = []
        well_known_ports = {
            21: 'FTP (risque: authentification claire)',
            22: 'SSH (risque: bruteforce constant)',
            23: 'Telnet (risque: tout en clair)',
            25: 'SMTP (risque: relais email)',
            53: 'DNS (risque: amplification DDoS)',
            80: 'HTTP (risque: web attacks)',
            443: 'HTTPS (risque: moins mais surveiller)',
            445: 'SMB (risque: EternalBlue, partages)',
            1433: 'MSSQL (risque: bruteforce)',
            3306: 'MySQL (risque: accès base)',
            3389: 'RDP (risque: ransomwares)',
            5432: 'PostgreSQL (risque: accès base)',
            5900: 'VNC (risque: accès écran)',
            8080: 'HTTP Alt (risque: souvent oublié)'
        }
        
        for port_info in ports:
            port = port_info['port']
            
            # Détection des risques
            if port in well_known_ports:
                risk_level = 'HAUT' if port in [21, 23, 445, 3389] else 'MOYEN'
                risks.append({
                    'port': port,
                    'service': well_known_ports[port],
                    'risk': risk_level,
                    'protocol': port_info['protocol'],
                    'process': port_info['process']
                })
            
            # Ports non standard mais ouverts
            elif 1 <= port <= 1023 and port not in well_known_ports:
                risks.append({
                    'port': port,
                    'service': 'Service système non standard',
                    'risk': 'MOYEN-ÉLEVÉ',
                    'protocol': port_info['protocol'],
                    'process': port_info['process'],
                    'note': 'Port well-known mais service non standard'
                })
        
        return risks
    
    def generate_report(listening_ports, active_connections, risks):
        """Génère un rapport d'audit"""
        timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
        
        report = {
            'timestamp': timestamp,
            'summary': {
                'total_listening': len(listening_ports),
                'total_established': len([c for c in active_connections if c['state'] == 'ESTAB']),
                'high_risk_ports': len([r for r in risks if r['risk'] == 'HAUT']),
                'medium_risk_ports': len([r for r in risks if r['risk'] == 'MOYEN'])
            },
            'listening_ports': listening_ports,
            'risks': risks,
            'recommendations': []
        }
        
        # Génération des recommandations
        if report['summary']['high_risk_ports'] > 0:
            report['recommendations'].append(
                f"Fermer immédiatement {report['summary']['high_risk_ports']} port(s) à risque élevé"
            )
        
        if report['summary']['total_listening'] > 10:
            report['recommendations'].append(
                "Réduire la surface d'attaque: trop de ports ouverts"
            )
        
        # Recommandations spécifiques
        for risk in risks:
            if risk['port'] == 23:
                report['recommendations'].append("REMPLACER Telnet (port 23) par SSH (port 22)")
            elif risk['port'] == 21:
                report['recommendations'].append("REMPLACER FTP (port 21) par SFTP/SCP sur SSH")
            elif risk['port'] == 3389 and risk['protocol'] == 'TCP':
                report['recommendations'].append("Sécuriser RDP (port 3389) avec VPN ou saut SSH")
        
        return report
    
    def main():
        print("🔍 PCTAMALOU - Audit des ports et connexions")
        print("=" * 60)
        
        # 1. Collecte des données
        print("\n[1/4] Collecte des ports en écoute...")
        ss_output = run_command("sudo ss -tulnp 2>/dev/null || ss -tulnp")
        listening_ports = parse_ss_output(ss_output)
        
        print("[2/4] Analyse des connexions actives...")
        established_output = run_command("ss -tan state established 2>/dev/null || netstat -tan | grep ESTABLISHED")
        
        # 2. Analyse des risques
        print("[3/4] Évaluation des risques...")
        risks = analyze_ports(listening_ports)
        
        # 3. Génération du rapport
        print("[4/4] Génération du rapport...")
        
        # Analyse des connexions actives simplifiée
        active_connections = []
        for line in established_output.strip().split('\n'):
            if line and 'ESTAB' in line:
                active_connections.append({'state': 'ESTAB', 'line': line})
        
        report = generate_report(listening_ports, active_connections, risks)
        
        # 4. Affichage
        print(f"\n📊 RAPPORT D'AUDIT - {report['timestamp']}")
        print(f"• Ports en écoute: {report['summary']['total_listening']}")
        print(f"• Connexions établies: {report['summary']['total_established']}")
        print(f"• Ports à risque élevé: {report['summary']['high_risk_ports']}")
        print(f"• Ports à risque moyen: {report['summary']['medium_risk_ports']}")
        
        if risks:
            print("\n⚠️  PORTS À RISQUE DÉTECTÉS:")
            for risk in risks:
                print(f"  • Port {risk['port']} ({risk['protocol']}): {risk['service']}")
                print(f"    Risque: {risk['risk']} - Processus: {risk['process'][:50]}")
        
        if report['recommendations']:
            print("\n💡 RECOMMANDATIONS:")
            for i, rec in enumerate(report['recommendations'], 1):
                print(f"  {i}. {rec}")
        
        # 5. Export JSON
        with open('port_audit_report.json', 'w') as f:
            json.dump(report, f, indent=2, default=str)
        print(f"\n💾 Rapport exporté: port_audit_report.json")
        
        # 6. Liste complète des ports
        print("\n📋 LISTE COMPLÈTE DES PORTS EN ÉCOUTE:")
        for port in listening_ports:
            print(f"  {port['protocol']} {port['ip']}:{port['port']} - {port['state']} - {port['process'][:30]}")
    
    if __name__ == "__main__":
        main()
  6. Exercices pratiques avancés

    Exercice 1 : Détection de connexions suspectes

    # Recherche de connexions vers des ports inhabituels
    echo "=== CONNEXIONS VERS PORTS NON STANDARD ==="
    sudo ss -tan state established | awk '$5 ~ /:[0-9]+$/ {
        split($5, a, ":");
        port = a[2];
        if (port < 1 || port > 65535) next;
        if (port != 22 && port != 80 && port != 443 && port != 53) {
            print "Connexion suspecte:", $0;
        }
    }' | head -20
    
    # Connexions sortantes nombreuses (possible beaconing)
    echo -e "\n=== IPS AVEC PLUSIEURS CONNEXIONS SORTANTES ==="
    sudo ss -tan state established | awk '$5 ~ /:/ {
        split($5, a, ":");
        ip = a[1];
        conns[ip]++;
    }
    END {
        for (ip in conns) {
            if (conns[ip] > 10 && ip != "0.0.0.0" && ip != "127.0.0.1") {
                print ip, "a", conns[ip], "connexions établies";
            }
        }
    }' | sort -k3 -nr

    Exercice 2 : Monitoring en temps réel

    # Watch des connexions (rafraîchissement toutes les 2 secondes)
    watch -n 2 "sudo ss -tan state established | tail -20"
    
    # Log des nouvelles connexions TCP
    sudo tcpdump -i any -n "tcp[tcpflags] & (tcp-syn) != 0 and (tcp[tcpflags] & (tcp-ack) == 0)" -c 10
    
    # Script de monitoring simple
    cat > monitor_ports.sh << 'EOF'
    #!/bin/bash
    echo "Monitoring des ports - PCTAMALOU S07"
    echo "Appuyez sur Ctrl+C pour arrêter"
    
    while true; do
        clear
        echo "=== $(date) ==="
        echo ""
        echo "Ports en écoute:"
        sudo ss -tlnp | head -15
        echo ""
        echo "Connexions établies:"
        sudo ss -tan state established | head -15
        sleep 5
    done
    EOF
    chmod +x monitor_ports.sh
    # ./monitor_ports.sh

🎯 Défi d'analyse avancé

Créez un système de détection d'anomalies réseau qui :

  1. Établit une baseline des ports normalement ouverts
  2. Surveille en temps réel les nouveaux ports en écoute
  3. Détecte les connexions vers des destinations suspectes (IPs blacklistées)
  4. Identifie les patterns de beaconing (connexions périodiques)
  5. Génère des alertes avec niveaux de priorité
  6. Exporte les logs au format JSON pour intégration SIEM

Indices : Utilisez ss en diff, comparez avec des fichiers de baseline, utilisez des listes d'IPs suspectes (ex: https://github.com/firehol/blocklist-ipsets).

📋 Objectif de la semaine – Checklist de validation

✅ Compétences techniques acquises

  • Utiliser ss et netstat pour analyser les ports
  • Différencier TCP (connecté) et UDP (non connecté)
  • Comprendre et expliquer le handshake TCP 3-way
  • Identifier les états TCP (LISTEN, ESTABLISHED, etc.)
  • Évaluer les risques des ports ouverts
  • Automatiser l'analyse avec des scripts Python

🧠 Changement mental accompli

  • Voir chaque port ouvert comme une surface d'attaque potentielle
  • Comprendre que "écouter ≠ servir" - on peut écouter sans servir utilement
  • Penser en termes d'états de connexion, pas juste de ports
  • Appliquer le principe de moindre privilège aux services réseau

🔐 Bonne pratique de sécurité réseau :

Implémentez ces règles immédiatement :

  1. Fermez tous les ports inutiles (netfilter/iptables)
  2. Utilisez des ports non standard pour les services sensibles (ex: SSH sur 2222)
  3. Limitez l'accès par IP source (whitelist)
  4. Surveillez les nouvelles connexions (journalisation)
  5. Testez régulièrement depuis l'extérieur (scans externes)

📚 Ressources gratuites recommandées

Pour approfondir :

⚠️ Pièges courants à éviter

  • Fermeture port 0 : Réservé, ne pas l'utiliser
  • SSH sur port 22 : Cible constante, déplacez-le ou protégez-le fortement
  • Netstat obsolète : Préférez ss (plus rapide, plus d'infos)
  • Oublier IPv6 : Vérifiez aussi les sockets IPv6 (ss -6)
  • TIME_WAIT accumulation : Normale, mais surveiller si excessive

🔮 Frère d'armes,

Tu viens de maîtriser la cartographie des portes de la cité numérique.

Maintenant, quand tu regardes un serveur, tu ne vois plus une boîte noire. Tu vois :

• Les portes ouvertes (ports en écoute)
• Les conversations en cours (connexions établies)
• Les demandes d'entrée (SYN en attente)
• Les adieux (fermetures en cours)

Cette semaine, tu as appris à écouter le murmure du réseau. Tu comprends maintenant :

• Pourquoi SSH sur le port 22 est comme une porte d'entrée avec une pancarte "ENTREZ"
• Pourquoi Telnet est comme crier ses secrets dans la rue
• Pourquoi TCP est une conversation polie, UDP un message jeté par la fenêtre
• Pourquoi chaque port ouvert doit avoir une raison d'être

Tu as développé le sixième sens du Gardien réseau : la capacité à sentir ce qui écoute, à voir ce qui communique, à anticiper ce qui pourrait attaquer.

Dans la semaine 8, nous passerons de l'observation à l'exploration active. Nous apprendrons à scanner les réseaux, à découvrir ce qui est caché, à cartographier ce qui est invisible.

Mais désormais, tu as une compétence fondamentale : tu sais auditer les accès. Et en cybersécurité, auditer les accès, c'est contrôler le périmètre.

Pratique. Analyse. Sécurise. Chaque port que tu comprends est une porte que tu sais verrouiller.

Tu n'es plus un simple utilisateur du réseau. Tu es devenu son gardien.

— Platon-Y