# Strategie de Blocage Automatique d'IP

## Vue d'ensemble

Le systeme de blocage IP protege l'application contre les intrusions, scans et brute-force tout en **evitant les faux positifs** sur les utilisateurs legitimes.

**Principe cle** : une IP depuis laquelle un utilisateur s'est deja connecte avec succes ne sera jamais bloquee pour des echecs de login. Seul le verrouillage de compte s'applique dans ce cas.

---

## Architecture

```
Requete entrante
    |
    v
[IpBlockingRequestListener] (priorite 512 - tres tot)
    |-- IP bloquee ? --> Reponse 403 (JSON ou HTML)
    |-- IP OK --> Continue vers le firewall
    v
[Firewall Symfony]
    |-- Echec login --> [AuthenticationFailureListener]
    |                       |
    |                       v
    |                   [IpBlockingService::recordFailedAttempt()]
    |                       |-- IP whitelistee ? --> Skip
    |                       |-- Analyse de menace (score 0-100)
    |                       |-- Score >= seuil ?
    |                       |       |-- IP connue + pas de scan --> Notification seulement
    |                       |       |-- Sinon --> BLOCAGE PROGRESSIF
    |                       |-- Score entre 70%-100% du seuil --> Notification
    |
    |-- Succes login --> [LoginSuccessListener]
                            |-- IP locale ? --> Skip validations
                            |-- Nouveau pays ? --> Code de validation
                            |-- Nouvelle IP ? --> Code de validation (si active)
```

---

## Scoring de Menace (0-100 points)

| Critere | Points | Condition |
|---------|--------|-----------|
| Echecs de login | 15/echec (max 50) | Tentatives echouees dans la derniere heure |
| Brute-force distribue | 10/email (max 40) | 3+ emails differents tentes depuis meme IP |
| Proxy/VPN/TOR | +25 | Detection via geolocalisation |
| Pays a risque | +10 | IP d'un pays dans la liste configurable |
| Paths suspects | +30 | 3+ requetes vers /wp-login, /.env, etc. |
| Taux d'erreur eleve | +20 | >80% d'erreurs sur >10 requetes (1h) |
| Requetes rapides | +25 | >60 requetes/minute |
| Blocs precedents | 10/bloc (max 30) | Historique de blocages de cette IP |

**Seuil de blocage** : 50 points (configurable)

---

## Protection Anti Faux-Positifs

### IPs Connues (Smart Whitelist)

Une IP est "connue" si un login **reussi** a eu lieu depuis cette IP dans les **30 derniers jours**.

| | IP connue | IP inconnue |
|---|---|---|
| **Seuil de blocage** | 150 (x3) | 50 |
| **Echecs login** | NE BLOQUE PAS l'IP | Ajoute au score |
| **Scanning** | BLOQUE (meme IP connue) | BLOQUE |
| **Verrouillage compte** | S'applique (3e/5e tentative) | S'applique |

### Scenario type : utilisateur qui oublie son mot de passe

```
Tentative 1 : echec --> Score IP = 15 (< seuil 150 pour IP connue) --> OK
Tentative 2 : echec --> Score IP = 30 (< 150) --> OK
Tentative 3 : echec --> AVERTISSEMENT EMAIL a l'utilisateur
Tentative 4 : echec --> Score IP = 60 (< 150) --> OK
Tentative 5 : echec --> COMPTE VERROUILLE (isActive=false) + email admins
                        IP NON BLOQUEE (car connue, pas de scan)
```

### Scenario type : attaquant brute-force

```
IP inconnue tente email1 : echec --> Score = 15
IP inconnue tente email2 : echec --> Score = 30
IP inconnue tente email3 : echec --> Score = 45 + 30 (3 emails) = 75 --> BLOQUEE 30 min
```

### Scenario type : scanner automatise

```
IP inconnue envoie 5 requetes vers /.env, /wp-login, /.git
    --> Score = 30 (paths suspects) --> BLOQUEE 30 min
IP revient apres 30 min, refait la meme chose
    --> Score = 30 + 10 (1 bloc precedent) = 40 + 30 (paths) = 70 --> BLOQUEE 2h
3e fois --> BLOQUEE 24h
4e fois --> BLOQUEE PERMANENT
```

---

## Blocage Progressif

| Nombre de blocs precedents | Duree |
|---|---|
| 0 (1er blocage) | 30 minutes |
| 1 | 2 heures |
| 2 | 24 heures |
| 3+ | **Permanent** |

---

## 2FA et Verrouillage de Compte

Le systeme de blocage IP coopere avec le verrouillage de compte :

| Situation | Action |
|---|---|
| 3 echecs sur un compte | Email d'avertissement a l'utilisateur |
| 5 echecs, 2FA OFF | Compte verrouille + IP bloquee (si inconnue) + email admins |
| 5 echecs, 2FA ON | Compte NON verrouille (protege par 2FA) + email admins |

---

## Paths Suspects (Scanning Detection)

Requetes vers ces chemins sont comptabilisees comme suspectes :

```
/wp-login, /wp-admin, /wp-content, /wp-includes
/.env, /.git, /phpinfo
/xmlrpc.php, /actuator, /solr
/console, /vendor/phpunit, /telescope, /debug
/phpmyadmin, /pma, /administrator, /cgi-bin
```

Configurable dans `config/services.yaml` : `app.ip_blocking.suspicious_paths`

---

## Configuration

### .env

```env
ENABLE_AUTO_IP_BLOCKING=true       # Activer le blocage automatique
IP_THREAT_SCORE_THRESHOLD=50       # Seuil de base (x3 pour IPs connues)
IP_AUTO_BLOCK_DURATION=3600        # Duree par defaut (non utilise en mode progressif)
```

### config/services.yaml

```yaml
app.ip_blocking.notification_only: false        # false = blocage reel
app.ip_blocking.threat_threshold: 50            # Seuil de base
app.ip_blocking.whitelist: ['127.0.0.1', '::1'] # IPs jamais bloquees
app.ip_blocking.suspicious_countries: []         # Codes pays a risque
app.ip_blocking.suspicious_paths: [...]          # Chemins de scan
```

---

## Maintenance

### Nettoyage automatique (cron)

```bash
# Toutes les 5 minutes : desactiver les blocks expires
*/5 * * * * cd /path/to/project && php bin/console app:ip-blocks:cleanup --no-interaction

# Mode dry-run pour verifier
php bin/console app:ip-blocks:cleanup --dry-run

# Retention personnalisee (defaut: 90 jours)
php bin/console app:ip-blocks:cleanup --retention-days=60
```

### Administration

Le panneau admin (`/admin/security/ip`) permet de :
- Voir le dashboard (stats, top pays, blocks recents)
- Lister/filtrer les blocks (IP, pays, type, date)
- Bloquer/debloquer manuellement
- Voir les details (tentatives, requetes HTTP)
- Rendre un block permanent
- Nettoyage en masse

---

## Fichiers Cles

| Fichier | Role |
|---------|------|
| `src/Service/Security/IpBlockingService.php` | Scoring, blocage, whitelist |
| `src/EventListener/IpBlockingRequestListener.php` | Interception requetes bloquees |
| `src/EventListener/AuthenticationFailureListener.php` | Trigger sur echec login |
| `src/Entity/IpBlock.php` | Entite de block |
| `src/Repository/IpBlockRepository.php` | Requetes BDD |
| `src/Repository/LoginAttemptRepository.php` | Historique login (smart whitelist) |
| `src/Repository/HttpRequestLogRepository.php` | Detection scanning |
| `src/Command/CleanExpiredIpBlocksCommand.php` | Nettoyage cron |
| `config/services.yaml` | Configuration seuils/paths |

---

## Diagramme de Decision

```
          Echec de login
               |
      IP whitelistee ?
         /         \
       Oui         Non
        |            |
      Skip     Analyse menace
               (score 0-100)
                    |
            IP connue ? --------+
            /        \          |
          Oui       Non         |
           |          |         |
     seuil=150   seuil=50      |
           |          |         |
     score >= ?   score >= ?    |
      /     \      /     \     |
    Non     Oui  Non     Oui   |
     |        |    |       |   |
   Skip   Scan?  Skip   BLOCK |
          /   \         (progressif)
        Oui   Non
         |      |
       BLOCK  Notif
      seulement
```
