Limitation de débit

OxPHP embarque un limiteur de débit par IP, il n'y a donc aucune dépendance externe ni infrastructure à exécuter. Une fois activé, il comptabilise le nombre de requêtes par IP cliente et renvoie une réponse 429 Too Many Requests lorsqu'un client dépasse le seuil configuré.

Fonctionnement

Le limiteur de débit s'appuie sur un compteur à fenêtre fixe indexé par l'adresse IP du client. Chaque IP dispose de son propre compteur et de sa propre fenêtre indépendants.

  1. Lorsqu'une requête arrive, OxPHP recherche l'IP cliente dans son suivi interne.
  2. Si aucune entrée n'existe, ou si la fenêtre courante a expiré, une nouvelle fenêtre démarre avec le compteur à zéro.
  3. Le compteur s'incrémente à chaque requête.
  4. Si le compteur dépasse RATE_LIMIT, le serveur renvoie immédiatement une réponse 429 accompagnée des en-têtes de limitation de débit. La requête est rejetée avant le routage ou l'exécution de PHP.

Les requêtes limitées apparaissent tout de même dans les journaux d'accès et les métriques.

Configuration

Variable Par défaut Description
RATE_LIMIT 0 Nombre maximal de requêtes par IP dans la fenêtre. 0 désactive totalement la limitation de débit, sans aucun surcoût
RATE_WINDOW_SECONDS 60 Durée de la fenêtre de limitation de débit, en secondes
bash
# Allow 100 requests per IP per 60-second window RATE_LIMIT=100 RATE_WINDOW_SECONDS=60

En-têtes de réponse

Les requêtes rejetées renvoient une réponse 429 Too Many Requests avec les en-têtes suivants :

En-tête Description
Retry-After Nombre de secondes avant la réinitialisation de la fenêtre courante
x-ratelimit-limit Nombre maximal de requêtes autorisées par fenêtre
x-ratelimit-remaining Requêtes restantes dans la fenêtre courante (0 lorsque la limite est atteinte)
x-ratelimit-reset Nombre de secondes avant la réinitialisation de la fenêtre courante
x-request-id ID de requête permettant de corréler cette réponse avec les journaux d'accès

Exemple de réponse 429 :

http
HTTP/1.1 429 Too Many Requests Retry-After: 45 x-ratelimit-limit: 100 x-ratelimit-remaining: 0 x-ratelimit-reset: 45 x-request-id: 67e2a1f412341a2b0042 429 Too Many Requests

Dépannage

Des utilisateurs légitimes sont soumis à la limitation de débit

Votre seuil est peut-être trop bas pour les schémas de trafic réels. Vérifiez le taux de réponses 429 dans vos métriques et ajustez RATE_LIMIT ou RATE_WINDOW_SECONDS en conséquence.

Vérifiez le nombre de requêtes limitées :

bash
curl http://localhost:9090/metrics | grep rate_limited

Solution : augmentez RATE_LIMIT ou allongez RATE_WINDOW_SECONDS pour laisser plus de marge aux clients.

Des utilisateurs derrière un NAT d'entreprise partagent le même compteur d'IP

OxPHP limite le débit par IP source. Tous les utilisateurs derrière un NAT ou un proxy partagé partagent un seul compteur. Si cela pose problème, envisagez de désactiver le limiteur intégré d'OxPHP (RATE_LIMIT=0) et d'appliquer la limitation de débit à un niveau supérieur (par exemple sur votre répartiteur de charge ou votre passerelle API), là où vous avez accès aux identifiants des utilisateurs.

Derrière un reverse proxy ?

Définissez TRUSTED_PROXIES pour que la limitation de débit utilise la véritable IP cliente au lieu de celle du proxy. Voir Proxys de confiance.

La limitation de débit ne fonctionne pas entre plusieurs instances

Le limiteur de débit d'OxPHP est en mémoire et propre à chaque instance. Si vous exécutez plusieurs instances OxPHP derrière un répartiteur de charge, chacune tient ses propres compteurs indépendants. Un client peut envoyer RATE_LIMIT requêtes à chaque instance sans déclencher de 429. Pour une limitation de débit coordonnée entre les instances, utilisez un limiteur externe au niveau du répartiteur de charge ou de la passerelle API.

La mémoire augmente lors d'attaques par rotation d'IP

OxPHP suit jusqu'à 100 000 adresses IP uniques. Lorsque cette limite est atteinte, les entrées expirées sont purgées avant l'ajout de nouvelles. Si vous constatez une hausse de la mémoire due à un attaquant qui fait tourner rapidement les IP, le nettoyage automatique limite l'impact à une quantité de mémoire bornée.

Exemple Docker

compose.yaml
services: app: image: ghcr.io/oxphp/oxphp:0.10.0 ports: - "8080:80" environment: RATE_LIMIT: "100" RATE_WINDOW_SECONDS: "60" volumes: - ./app:/var/www/html:ro

Bonnes pratiques

  • Commencez prudemment. Débutez avec une limite plus basse (par exemple 60 requêtes par minute) et augmentez-la en fonction des schémas de trafic observés. Il est plus facile d'assouplir des limites que de rétablir un serveur surchargé.
  • Utilisez un limiteur de débit partagé pour les déploiements multi-instances. Le limiteur de débit d'OxPHP est propre à chaque instance. Pour une limitation coordonnée entre les instances, appliquez la limitation de débit au niveau du répartiteur de charge ou de la passerelle API.
  • Surveillez les taux de réponses 429. Suivez la proportion de requêtes limitées dans vos métriques afin de détecter des seuils mal configurés ou des pics de trafic inattendus.

Remarques

  • Algorithme à fenêtre fixe. Le limiteur utilise un compteur à fenêtre fixe, et non une fenêtre glissante. Un client peut envoyer jusqu'à 2x la limite configurée en rafale, à la frontière entre deux fenêtres.
  • Par IP uniquement. La limitation de débit est indexée par adresse IP source. Il n'existe aucune prise en charge de clés personnalisées comme une clé d'API ou un identifiant utilisateur.
  • État en mémoire. Les compteurs de limitation de débit ne sont pas partagés entre plusieurs instances OxPHP.
  • Nettoyage automatique. Les entrées expirées sont nettoyées lorsque le suivi dépasse 100 000 IP, en supprimant toutes les entrées dont les fenêtres ont expiré.

Voir aussi