> For the complete documentation index, see [llms.txt](https://docs.ipcheck.ing/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.ipcheck.ing/developer/fr/configuration/security-options.md).

# Options de sécurité

Le backend de MyIP proxy plusieurs API tierces, dont certaines sont payantes. Laissé grand ouvert, une instance publique devient un proxy anonyme et gratuit pour quiconque la trouve.

Voyez la protection comme deux couches, dans cet ordre :

1. **Le bord (couche primaire recommandée).** Un CDN/WAF devant votre origine — Cloudflare est l’exemple utilisé ci-dessous — bloque le trafic abusif avant même qu’il n’atteigne votre serveur, avec des outils bien plus avancés que ceux qu’une application peut embarquer : détection de bots gérée, règles flexibles de limitation de débit, défis, et vue globale des IP des attaquants.
2. **L’application elle-même (le filet de sécurité).** Quatre variables d’environnement ajoutent une dernière ligne de défense au backend. Elles valent la peine d’être définies même derrière un bord — ce sont elles qui vous protègent lorsque quelqu’un découvre la véritable adresse de votre origine et contourne totalement le bord — mais elles constituent une mesure de secours, pas la défense principale.

## Protéger d’abord au bord (recommandé)

Tout CDN/WAF avec des règles de débit par IP fonctionne de la même manière ; les étapes ci-dessous utilisent Cloudflare parce que c’est le choix le plus courant et que son offre gratuite couvre déjà l’essentiel.

{% stepper %}
{% step %}

#### Proxyfiez vos enregistrements DNS via Cloudflare

Dans le panneau DNS de Cloudflare, conservez l’enregistrement de votre nom d’hôte MyIP **Proxyfie** (nuage orange), afin que tout le trafic passe par le bord de Cloudflare. MyIP est conçu pour cela : le backend lit déjà `CF-Connecting-IP` pour identifier les vraies IP clients, et ses routes cacheables `/api/*` sont servies depuis le cache de bord, ce qui absorbe une grande partie de la charge avant qu’elle ne vous atteigne.
{% endstep %}

{% step %}

#### Ajoutez une règle de limitation de débit pour `/api/*`

Sous **Sécurité → WAF → Règles de limitation de débit**, créez une règle correspondant au chemin de votre API — par exemple, l’expression `(http.request.uri.path wildcard "/api/*")` — et bloquez l’IP source lorsqu’elle dépasse votre seuil. La limitation de débit est disponible sur tous les plans ; le nombre de règles et les options de fenêtre varient selon le plan. Comme le cache de bord répond déjà aux requêtes répétées, les visiteurs légitimes n’ont que rarement besoin d’un volume élevé de requêtes — commencez plus strict que vous ne le pensez, et relâchez si de vrais utilisateurs se plaignent.
{% endstep %}

{% step %}

#### Activez la protection contre les bots

Activez **Bot Fight Mode** (Sécurité → Bots). La plupart des abus d’une instance MyIP publique sont des extractions automatisées des points de terminaison de géolocalisation, ce qui est précisément la cible ici. Si votre plan dispose de règles WAF personnalisées, un **Défi géré** sur le trafic non navigateur vers `/api/*` est une alternative plus douce qui ne bloque jamais définitivement un vrai utilisateur.
{% endstep %}

{% step %}

#### Verrouillez votre origine

Les règles de bord n’aident que si le trafic ne peut pas les contourner. Configurez le pare-feu de votre serveur d’origine pour n’accepter HTTP(S) que depuis [les plages d’IP de Cloudflare](https://www.cloudflare.com/ips/) — ou retirez totalement l’origine de l’internet public avec Cloudflare Tunnel. Si l’origine répond aux requêtes directes, un attaquant qui découvre son adresse contourne toutes les règles ci-dessus ; c’est exactement pour ce scénario que les variables au niveau de l’application ci-dessous existent.
{% endstep %}
{% endstepper %}

{% hint style="info" %}
Les requêtes servies depuis le cache de Cloudflare n’atteignent jamais l’origine, elles sont donc invisibles pour les limiteurs au niveau de l’application ci-dessous — une autre raison pour laquelle la maîtrise du volume doit se faire au bord.
{% endhint %}

## Le filet de sécurité propre à l’application

Quatre variables d’environnement construisent la couche de secours dans le backend. Les quatre sont facultatives et désactivées (ou permissives) par défaut.

| Variable                           | Objectif                                           | Par défaut             |
| ---------------------------------- | -------------------------------------------------- | ---------------------- |
| `ALLOWED_DOMAINS`                  | Quels sites peuvent appeler `/api/*`               | `localhost` uniquement |
| `SECURITY_RATE_LIMIT`              | Plafond de requêtes dur par IP                     | `0` — désactivé        |
| `SECURITY_DELAY_AFTER`             | Ralentissement progressif par IP                   | `0` — désactivé        |
| `SECURITY_BLACKLIST_LOG_FILE_PATH` | Journal sur disque des IP soumises à la limitation | vide — aucun fichier   |

## `ALLOWED_DOMAINS` — la passerelle Referer

Chaque `/api/*` route passe par une vérification de référent. Le backend lit l’en-tête `Referer` en extrait son **nom d’hôte**et exige que ce nom d’hôte figure dans la liste d’autorisation.

La liste d’autorisation est `localhost` plus les entrées séparées par des virgules dans `ALLOWED_DOMAINS`.

Les rejets sont `403`:

| Situation                                               | Réponse                          |
| ------------------------------------------------------- | -------------------------------- |
| Aucun `Referer` en-tête du tout                         | `{"error": "Que faites-vous ?"}` |
| Referer présent, nom d’hôte non autorisé (ou illisible) | `{"error": "Accès refusé"}`      |

{% hint style="danger" %}
**Si vous servez MyIP sur un vrai domaine, vous devez définir ceci.** Avec `ALLOWED_DOMAINS` vide, seul `localhost` passe — donc un déploiement accessible via `https://ip.example.com` ou `http://192.168.1.10:18966` obtient `403` sur chaque appel d’API, et l’application semble cassée alors que la page statique se charge correctement.
{% endhint %}

Règles à garder en tête :

* **Noms d’hôte uniquement.** Pas de schéma, pas de port, pas de chemin : `example.com`, pas `https://example.com:443/`.
* **Correspondances exactes.** `example.com` ne couvre pas `www.example.com`. Listez les deux.
* **Les adresses IP comptent comme des noms d’hôte.** Accéder à l’application via `http://192.168.1.10:18966` signifie ajouter `192.168.1.10`.
* **`localhost` est toujours autorisé**, donc le développement local n’a jamais besoin de configuration.

{% code title=".env" %}

```bash
ALLOWED_DOMAINS="example.com,www.example.com,ip.example.com"
```

{% endcode %}

{% hint style="warning" %}
La vérification du référent est un moyen de dissuasion contre les abus, pas une authentification. N’importe quel client peut envoyer un en-tête `Referer` arbitraire. Elle bloque le hotlinking occasionnel et les scripts opportunistes ; elle n’arrête pas un scraper déterminé. Combinez-la avec la limitation de débit.
{% endhint %}

Derrière un proxy inverse, assurez-vous que votre proxy transmet l’en-tête `Referer` sans le modifier. Voir [Proxy inverse et domaines](/developer/fr/getting-started/reverse-proxy-and-domains.md).

## `SECURITY_RATE_LIMIT` — plafond dur

Un plafond de requêtes par IP sur `/api/*`, appuyé par `express-rate-limit`.

* **Fenêtre**: 20 minutes, glissante.
* **Limite**: le nombre que vous définissez. `0` ou vide signifie que le limiteur n’est jamais monté.
* **Au-delà de la limite**: `429` avec `{"message": "Trop de requêtes"}`.
* **Route exemptée**: `/api/monitoring`, le tunnel Sentry, qui a son propre limiteur — voir [Surveillance des erreurs](/developer/fr/configuration/error-monitoring.md).

{% hint style="info" %}
La ligne de démarrage affiche `🛡️ Limiteur de débit activé — N requêtes par 60 minutes`. La fenêtre appliquée dans le code est **20 minutes**.
{% endhint %}

### Ce qui est journalisé

Le backend journalise le moment où une IP franchit le seuil — **une seule fois**, au moment de la transition, et non à chaque requête bloquée suivante. Cela évite qu’un client abusif martelant un point de terminaison limité noie vos journaux.

```
AVERTISSEMENT : IP soumise à limitation de débit
    ip: "203.0.113.45"
```

Lorsqu’un DSN backend Sentry est configuré, cette même ligne est répliquée vers Sentry.

### Comment l’IP client est déterminée

Le limiteur et la ligne de journal déterminent l’IP de l’appelant dans cet ordre :

1. `CF-Connecting-IP`
2. la première entrée de `X-Forwarded-For`
3. `CF-Connecting-IPv6`
4. l’adresse socket vue par Express

L’application tourne avec `trust proxy` réglé sur `1`, ce qui signifie qu’elle fait confiance à exactement un saut d’en-têtes de proxy.

{% hint style="warning" %}
Si votre proxy inverse ne définit pas `X-Forwarded-For`, chaque requête semble provenir du proxy — une seule IP, un quota partagé, et le premier visiteur très actif bloque tout le monde. Vérifiez le transfert des en-têtes avant d’activer le limiteur.
{% endhint %}

## `SECURITY_DELAY_AFTER` — ralentissement progressif

Un compagnon plus doux, appuyé par `express-slow-down`. Au lieu de rejeter, il retarde.

* **Fenêtre**: 60 minutes, glissante.
* **Requêtes gratuites**: le nombre que vous définissez. Les requêtes au-delà sont traitées lentement.
* **Délai**: `400 ms × nombre total de requêtes effectuées dans la fenêtre`.
* `0` ou vide signifie que le middleware n’est jamais monté.
* Même `/api/monitoring` exemption.

{% hint style="warning" %}
Le délai est calculé à partir du **total** des requêtes, et non du dépassement — il commence donc haut et grimpe vite. Avec `SECURITY_DELAY_AFTER="40"`, la requête 41 attend déjà environ 16 secondes ; avec `"100"`, la requête 101 attend environ 40 secondes. Choisissez une valeur en sachant que la première requête bridée implique déjà une longue attente, et attendez-vous à des timeouts côté client au-delà.
{% endhint %}

Le ralentissement et la limitation de débit s’additionnent. Traitez `SECURITY_RATE_LIMIT` comme la défense principale et n’utilisez le ralentissement que lorsque vous voulez que des rafales automatisées ralentissent au lieu d’échouer.

## `SECURITY_BLACKLIST_LOG_FILE_PATH` — journal sur disque

Optionnel. Lorsqu’il est défini, chaque transition de limitation de débit est aussi ajoutée à un fichier texte brut.

{% code title=".env" %}

```bash
SECURITY_BLACKLIST_LOG_FILE_PATH="logs/blacklist-ip.log"
```

{% endcode %}

* Le chemin est résolu **par rapport à la racine de l’application**. Les répertoires manquants sont créés.
* Une ligne CSV par IP : `ip,count,first-seen-timestamp`.
* L’horodatage correspond à l’heure locale de l’hôte avec un décalage UTC explicite, par ex. `2026-07-14 10:23:45 +0800`.
* Pour un récidiviste, le **compteur augmente et l’horodatage d’origine reste**, afin que vous puissiez voir quand une IP est apparue pour la première fois.

```
203.0.113.45,7,2026-07-14 10:23:45 +0800
198.51.100.9,1,2026-07-15 02:11:07 +0800
```

Le laisser vide ne change rien à l’application de la règle — le journal d’avertissement continue d’être émis. Le fichier sert aux déploiements qui veulent une trace permanente, par exemple pour alimenter un pare-feu ou un script de type fail2ban.

{% hint style="info" %}
Dans Docker, écrivez le journal sur un volume monté. Un chemin situé dans la couche inscriptible du conteneur disparaît lorsque le conteneur est recréé.
{% endhint %}

## Ordre des middlewares

Bon à savoir quand vous déboguez un `403` ou un `429`:

1. journalisation des requêtes HTTP, si `LOG_HTTP=true` — ainsi les 429 apparaissent dans le journal
2. Limiteur de débit (si activé)
3. Ralentissement (si activé)
4. Analyse du corps JSON
5. Passerelle Referer
6. Le gestionnaire de route

La limitation de débit se produit donc **avant** la vérification du référent. Une avalanche de requêtes avec un mauvais référent consomme quand même le quota du fautif — ce qui est le comportement souhaité.

Notez aussi qu’un CDN devant l’application sert des réponses mises en cache `/api/*` sans jamais atteindre l’origine, donc ces requêtes sont invisibles pour le limiteur. La plupart des routes à forte lecture sont mises en cache au bord.

## Valeurs de secours recommandées pour une instance publique

Même avec le bord configuré, définissez ces valeurs pour que l’origine puisse se défendre seule :

{% tabs %}
{% tab title="Node (.env)" %}
{% code title=".env" %}

```bash
ALLOWED_DOMAINS="example.com,www.example.com"
SECURITY_RATE_LIMIT="600"
SECURITY_BLACKLIST_LOG_FILE_PATH="logs/blacklist-ip.log"
```

{% endcode %}
{% endtab %}

{% tab title="Docker" %}

```bash
docker run -d -p 18966:18966 \
  -e ALLOWED_DOMAINS="example.com,www.example.com" \
  -e SECURITY_RATE_LIMIT="600" \
  -e SECURITY_BLACKLIST_LOG_FILE_PATH="logs/blacklist-ip.log" \
  -v "$(pwd)/logs:/app/logs" \
  --name myip \
  jason5ng32/myip:latest
```

{% endtab %}
{% endtabs %}

Ces chiffres sont un point de départ, pas une règle. Ajustez-les :

* Un chargement complet de page déclenche **de nombreuses** `/api/*` appels — sources d’IP, vérifications de connectivité, sondes DNS. Un seul visiteur consomme facilement des dizaines de requêtes par session.
* Réglez la limite trop bas et les utilisateurs normaux atteignent `429` en pleine phase de diagnostic.
* Surveillez le journal et les avertissements `IP soumise à limitation de débit` pendant une semaine, puis resserrez.
* Derrière du CGNAT ou un NAT d’entreprise, de nombreux vrais utilisateurs partagent une seule IP. Laissez de la marge.

{% hint style="success" %}
La superposition en une phrase : laissez le bord absorber et filtrer le volume, et dimensionnez généreusement ces variables pour qu’elles ne se déclenchent jamais que sur le trafic qui lui a échappé.
{% endhint %}

## Pages associées

* [Variables d’environnement](/developer/fr/reference/environment-variables.md) — la liste complète
* [Proxy inverse et domaines](/developer/fr/getting-started/reverse-proxy-and-domains.md) — les en-têtes que votre proxy doit transmettre
* [Journalisation](/developer/fr/configuration/logging.md) — où les avertissements apparaissent
* [Clés API optionnelles](/developer/fr/configuration/optional-api-keys.md) — les quotas que vous protégez


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.ipcheck.ing/developer/fr/configuration/security-options.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
