# DenyGrid ↔ MikroTik RouterOS — Connecteur / Passerelle

Passerelle qui fait entrer un ou plusieurs routeurs **MikroTik (RouterOS v7)** dans
DenyGrid **sans rien installer sur le routeur** et **sans modifier le serveur DenyGrid**.

Le connecteur tourne sur une VM / machine dédiée et, pour chaque routeur :

1. l'**enrôle** comme une « machine » DenyGrid (machine_id + api_key, auto-approuvé) ;
2. lit son **journal** via l'API RouterOS, en extrait les **tentatives d'intrusion**
   (échecs SSH, winbox, …) et les remonte à DenyGrid (`/events.php`) ;
3. DenyGrid **décide** (réputation / classification / autoban) — logique inchangée ;
4. le connecteur **redescend les bans** (IP + plages /24) dans une *address-list* du
   routeur via l'API RouterOS, avec un `timeout` = durée du ban.

```
 Routeur MikroTik  ──API REST──►  Connecteur (VM)  ──HTTPS──►  DenyGrid
     (RouterOS v7) ◄──API REST──      (ce service)  ◄──HTTPS──   (décide)
   /log (intrusions)             events + bans           réputation/autoban
   address-list (bans)
```

---

## 1. Prérequis

- **Côté DenyGrid** : récupérer votre **clé d'enrôlement** (32 caractères hex) dans
  l'interface (page d'ajout de machine / enrôlement). C'est la seule chose nécessaire.
- **Côté VM** : Linux avec **Python 3.7+** et `pip`.
- **Côté routeur** : **RouterOS v7.1+** (API REST), joignable depuis la VM.

---

## 2. Configuration du routeur MikroTik (à répéter sur chaque routeur)

> ⚠️ **Le modèle de permissions RouterOS est par *policy* (grossier), il n'existe pas
> d'ACL par commande.** « Accès limité au ban/déban » est donc obtenu par : un groupe
> *least-privilege* + un utilisateur **verrouillé sur l'IP du connecteur** + le service
> API **restreint à l'IP du connecteur**. Le compte ne peut ni ouvrir de shell, ni gérer
> les utilisateurs, ni lire les secrets.

Remplacez `A.B.C.D` par l'**IP de la VM connecteur**.

### 2.1 Créer un groupe à privilèges minimaux
```rsc
/user group add name=denygrid-api \
  policy=read,write,api \
  comment="DenyGrid connector - least privilege"
```
- `read` : lire le journal et l'address-list.
- `write` : gérer l'address-list + créer la règle de drop.
- `api` : accès à l'API binaire.
- **Non accordés** (donc refusés) : `policy` (gestion des users), `ssh/telnet/ftp`
  (pas de shell), `reboot`, `sensitive` (pas de lecture des secrets), `web` (pas de
  WebFig/REST), `sniff`, `romon`…

### 2.2 Créer l'utilisateur de service, verrouillé sur l'IP du connecteur
```rsc
/user add name=denygrid-svc group=denygrid-api \
  password="UN_MOT_DE_PASSE_FORT" \
  address=A.B.C.D/32 \
  comment="DenyGrid connector"
```
`address=A.B.C.D/32` ⇒ ce compte ne peut se connecter **que** depuis le connecteur.

### 2.3 Activer l'API binaire `api-ssl` (8729), restreinte à l'IP du connecteur
> On utilise l'**API binaire** dédiée, **pas** le service web (`www`/`www-ssl` reste éteint).
```rsc
# Certificat auto-signé (api-ssl en exige un)
/certificate add name=denygrid-api common-name=router days-valid=3650
/certificate sign denygrid-api

# Activer api-ssl (port 8729), restreint à l'IP du connecteur
/ip service set api-ssl certificate=denygrid-api disabled=no address=A.B.C.D/32
```
> Le certificat étant auto-signé, mettez `"verify_tls": false` pour ce routeur dans la
> config du connecteur (défaut). Certificat reconnu → `true`.
>
> **Alternative sans TLS** (uniquement sur lien de confiance / VPN) : activer l'API en
> clair et mettre `"tls": false, "api_port": 8728` côté connecteur —
> `/ip service set api disabled=no address=A.B.C.D/32`.

### 2.4 Règle de ban (address-list + drop)
Le connecteur **crée automatiquement** la règle de drop au premier passage. Elle
équivaut à :
```rsc
/ip firewall raw add chain=prerouting action=drop \
  src-address-list=denygrid-blocked comment=denygrid-managed
```
- `raw / prerouting` : les IP bannies sont *droppées avant le conntrack* → le plus
  efficace, et cela protège aussi le trafic **routé** (le réseau derrière le routeur).
- Les entrées de l'address-list `denygrid-blocked` sont **gérées par le connecteur**
  (ajout avec `timeout` = durée du ban, suppression au déban/whitelist).
- Vous pouvez déplacer la règle dans l'ordre du chain `raw` selon votre politique.

### 2.5 Vérifier que les échecs de login sont journalisés
Par défaut RouterOS journalise déjà les échecs de login en mémoire. Pour être sûr /
augmenter la profondeur :
```rsc
/system logging action set memory memory-lines=1000
# (optionnel) topic 'account' pour plus de détail de login
/system logging add topics=account action=memory
```
Le connecteur lit `/log` (le buffer mémoire) et repère les lignes
`login failure for user <u> from <ip> via <service>`.

---

## 3. Installation du connecteur (sur la VM)

### 3.1 Méthode recommandée : l'installeur `install.sh`

L'installeur détecte tout seul s'il tourne **en root** ou **sans privilèges** :

```bash
# En root AVEC sudo :
sudo ./install.sh

# En root SANS sudo (Debian minimal) : passer root avec su - puis lancer :
su -
cd /chemin/vers/mikrotik-connector && ./install.sh

# SANS AUCUN privilège (utilisateur simple) → installe dans $HOME :
./install.sh
```

Il : installe la dépendance `requests`, crée l'arborescence, **génère `config.json`
en mode interactif** (URL DenyGrid, clé d'enrôlement, routeurs), installe le service
et le démarre.

| | Root (sudo ou `su -`) | Sans root |
|---|---|---|
| Dossier | `/opt/denygrid-mikrotik` | `$HOME/denygrid-mikrotik` |
| Dépendance | `apt install python3-requests` | venv Python (ou `pip --user`) |
| Compte | utilisateur système dédié `denygrid` | l'utilisateur courant |
| Service | `systemd` (système) | `systemctl --user` + linger, sinon **repli cron `@reboot`** |

Ajouter d'autres routeurs plus tard (interactif, redémarre le service) :
```bash
sudo ./install.sh --add-router        # (ou ./install.sh --add-router sans root)
```

Options : `--add-router` (ajouter un ou plusieurs routeurs), `--no-config` (config par
défaut sans questions), `--user` (forcer le mode utilisateur), `--uninstall`.

> L'URL de l'API DenyGrid est **`https://denygrid.com/api` par défaut** (dérivée du
> domaine) — l'installeur ne la demande pas, il demande seulement la **clé d'enrôlement**
> puis les **routeurs**.

### 3.2 Installation manuelle (référence)

```bash
# 1. Déposer les fichiers
sudo mkdir -p /opt/denygrid-mikrotik
sudo cp denygrid_mikrotik.py config.example.json requirements.txt /opt/denygrid-mikrotik/

# 2. Dépendance Python
sudo python3 -m pip install -r /opt/denygrid-mikrotik/requirements.txt

# 3. Utilisateur système dédié (non privilégié)
sudo useradd --system --home /opt/denygrid-mikrotik --shell /usr/sbin/nologin denygrid || true
sudo chown -R denygrid:denygrid /opt/denygrid-mikrotik

# 4. Configuration
sudo cp /opt/denygrid-mikrotik/config.example.json /opt/denygrid-mikrotik/config.json
sudo -u denygrid nano /opt/denygrid-mikrotik/config.json   # renseigner clé + routeurs
sudo chmod 600 /opt/denygrid-mikrotik/config.json          # contient des mots de passe
```

### config.json (voir `config.example.json`)
| Champ | Rôle |
|-------|------|
| `denygrid_url` | URL de l'API DenyGrid, ex. `https://denygrid.example.com/api` |
| `enrollment_key` | votre clé d'enrôlement DenyGrid (32 hex) |
| `poll_interval` | période de la boucle en secondes (défaut 60) |
| `routers[]` | un objet par routeur : `name, host, api_port, username, password, verify_tls`, (option) `address_list`, `drop_chain`, `scheme` |
| `sync_interval` | (option, défaut 300s) période **minimale** entre deux réconciliations de l'address-list. La lecture complète de la liste coûte cher : l'espacer garde la remontée des tentatives à la cadence de `poll_interval`. |
| `push_delay_ms` | (option, défaut 5) pause entre deux écritures API vers le routeur, pour ne pas le saturer lors d'un gros lot d'ajouts. |
| `timeout_refresh_interval` | (option, défaut 3600s) période entre deux rafraîchissements des `timeout` des entrées existantes. Le faire à chaque cycle coûtait une écriture API par ban (des milliers d'appels pour zéro changement). |
| `service_map` | (option) service RouterOS → `event_type` DenyGrid |

### Lancer en service systemd
```bash
sudo cp denygrid-mikrotik.service /etc/systemd/system/
sudo systemctl daemon-reload
sudo systemctl enable --now denygrid-mikrotik
journalctl -u denygrid-mikrotik -f      # suivre les logs
```

Test manuel (avant systemd) :
```bash
sudo -u denygrid DENYGRID_MIKROTIK_CONFIG=/opt/denygrid-mikrotik/config.json \
  python3 /opt/denygrid-mikrotik/denygrid_mikrotik.py
```

---

## 4. Vérification

1. **Dans DenyGrid** : chaque routeur apparaît comme une **machine** (nom = `name`).
2. **Tentatives** : provoquez un échec SSH sur le routeur → il doit remonter dans les
   *Événements* DenyGrid quelques dizaines de secondes plus tard.
3. **Bans** : une fois une IP bannie par DenyGrid, vérifiez sur le routeur :
   ```rsc
   /ip firewall address-list print where list=denygrid-blocked
   ```
   L'IP (ou la plage /24) doit y figurer avec un `timeout`.
4. **Déban / whitelist** : débannir/whitelister l'IP côté DenyGrid → elle disparaît de
   l'address-list au cycle suivant.

---

## 5. Notes & réglages

- **Types d'événements** : par défaut, `ssh`/`telnet` → `ssh_failed` et `ftp` →
  `ftp_failed` (ils déclenchent l'autoban DenyGrid **existant**). Les autres services
  (`winbox`, `api`, `web`) utilisent des types `mikrotik_*`. Pour qu'ils déclenchent un
  ban, ajoutez ces types à une **règle d'autoban** dans l'UI DenyGrid (c'est de la
  *config*, pas du code). Personnalisable via `service_map`.
- **Plages /24** : DenyGrid peut bannir des plages entières ; le connecteur les pousse
  telles quelles (`1.2.3.0/24`) dans l'address-list — RouterOS gère nativement le CIDR.
- **Bans globaux** : `firewall.php` renvoie aussi les bans réseau globaux DenyGrid, donc
  chaque routeur bénéficie de l'intelligence de tout le parc.
- **Robustesse** : un routeur injoignable n'empêche pas les autres ; le curseur de log
  est persistant (`state.json`) et gère les reboots du routeur.
- **Volume élevé** : le connecteur lit le buffer `/log` (borné). En cas de très forte
  volumétrie, préférez pousser les logs du routeur en **syslog** vers le connecteur
  (évolution possible) ; l'API-poll suffit pour un usage courant.
- **Limitation RouterOS** : pas d'ACL par commande → le compte a `write` (large) mais est
  confiné à l'IP du connecteur, sans shell, sans gestion des users, sans lecture des
  secrets. C'est le maximum réalisable nativement pour « limité au ban ».
