Module 3 — API Gateway, Reverse Proxy et Forward Proxy : la différence, testée en vrai
Bonne lecture et bon apprentissage ! Junior TSAFACK – 18/09/2026 Temps de lecture estimé : 16 minutes
Pourquoi ces trois notions se confondent
Section titled “Pourquoi ces trois notions se confondent”Forward proxy, reverse proxy et API Gateway sont trois briques qui font, au niveau du paquet réseau, exactement la même chose : elles reçoivent une requête HTTP et la retransmettent vers une autre machine. C’est pour ça qu’on les confond. La différence n’est pas technique au sens du protocole — c’est une différence de position dans l’architecture et de qui elles servent :
- Le forward proxy se place devant un groupe de clients et parle en leur nom au reste d’Internet. Il protège et contrôle le client.
- Le reverse proxy se place devant un groupe de serveurs et reçoit les requêtes en leur nom. Il protège et contrôle le serveur.
- L’API Gateway est un reverse proxy spécialisé pour les API : il fait tout ce qu’un reverse proxy fait, plus l’authentification, la limitation de débit, le routage vers plusieurs microservices et souvent la transformation des requêtes.
Le reste de ce module démontre ces trois comportements avec des instances réellement installées et interrogées dans l’environnement de ce cours (Nginx 1.24, Squid 6.14, HAProxy 2.8) — pas des extraits de documentation recopiés.
Forward proxy : Squid, au service du client
Section titled “Forward proxy : Squid, au service du client”Le scénario
Section titled “Le scénario”Une application Flask (catalogue-interne) tourne en local sur le port 5050. Un forward proxy Squid est configuré sur le port 3128. Le client choisit explicitement d’envoyer sa requête à travers ce proxy (curl -x http://127.0.0.1:3128 ...) — c’est la caractéristique clé d’un forward proxy : c’est le client qui le configure, pas le serveur cible qui l’impose.
http_port 3128acl localnet src 127.0.0.1http_access allow localnethttp_access deny allTest 1 — ACL qui refuse le client
Section titled “Test 1 — ACL qui refuse le client”En changeant une seule ligne (http_access allow localnet → http_access deny localnet), Squid rejette la requête avant même de la transmettre :
$ curl -x http://127.0.0.1:3128 http://127.0.0.1:5050/api/produitsHTTP/1.1 403 ForbiddenServer: squid/6.14X-Squid-Error: ERR_ACCESS_DENIED 0Via: 1.1 vm (squid/6.14)Le header Via: 1.1 vm (squid/6.14) est la preuve que c’est bien Squid qui a traité la requête, pas une réponse directe du backend.
Test 2 — ACL qui autorise, requête relayée avec succès
Section titled “Test 2 — ACL qui autorise, requête relayée avec succès”Après avoir remis http_access allow localnet, la même requête traverse réellement Squid puis atteint le backend :
$ curl -x http://127.0.0.1:3128 http://127.0.0.1:5050/api/produitsHTTP/1.1 200 OKServer: Werkzeug/3.1.8 Python/3.11.15Via: 1.1 vm (squid/6.14)
{"produits":["clavier","souris","ecran"],"service":"catalogue-interne"}Le journal d’accès Squid confirme les deux événements, dans l’ordre où ils se sont réellement produits :
$ cat access.log... 127.0.0.1 TCP_DENIED/403 3390 GET http://127.0.0.1:5050/api/produits - HIER_NONE/-... 127.0.0.1 TCP_MISS/200 303 GET http://127.0.0.1:5050/api/produits - HIER_DIRECT/127.0.0.1Ce que ce test démontre
Section titled “Ce que ce test démontre”Le client sait qu’il passe par un proxy (il le configure lui-même, via -x ou une variable http_proxy). Le serveur cible (127.0.0.1:5050), lui, ne sait rien de la politique d’accès qui vient d’être appliquée — pour lui, une requête est juste arrivée. C’est exactement le rôle d’un forward proxy en entreprise : contrôler et journaliser ce que les postes internes ont le droit d’atteindre à l’extérieur, filtrer les domaines interdits, mettre en cache des ressources fréquemment demandées, et anonymiser l’origine réelle du client vis-à-vis de la destination.
Reverse proxy : Nginx, au service du serveur
Section titled “Reverse proxy : Nginx, au service du serveur”Le scénario
Section titled “Le scénario”Le même backend Flask (127.0.0.1:5050) est maintenant placé derrière un reverse proxy Nginx sur le port 8081. Cette fois, c’est l’inverse : c’est l’opérateur du serveur qui configure le proxy, et le client n’a pas le choix — il ne peut pas décider de le contourner, puisque dans une vraie topologie réseau, le backend n’est routable que via ce proxy.
events {}http { server { listen 8081; location / { proxy_pass http://127.0.0.1:5050/; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; add_header X-Proxy-By "nginx-reverse-proxy" always; } }}Vérification réelle
Section titled “Vérification réelle”$ curl -D - http://127.0.0.1:8081/api/produitsHTTP/1.1 200 OKServer: nginx/1.24.0 (Ubuntu)Content-Type: application/jsonX-Proxy-By: nginx-reverse-proxy
{"produits":["clavier","souris","ecran"],"service":"catalogue-interne"}Ce que ce test démontre
Section titled “Ce que ce test démontre”Le client s’adresse à 127.0.0.1:8081 et n’a jamais eu besoin de connaître l’adresse 127.0.0.1:5050 du vrai backend — c’est exactement le miroir du forward proxy : là où le forward proxy cache le client au regard du serveur cible, le reverse proxy cache le serveur au regard du client. Le Module 1 de ce parcours a déjà montré, sur ce même principe, comment Nginx répartit la charge entre plusieurs backends et bascule automatiquement quand l’un d’eux tombe — c’est la responsabilité la plus classique d’un reverse proxy, mais pas la seule : il gère aussi la terminaison TLS, la compression, le cache de réponses, et fait écran de sécurité (le backend applicatif, potentiellement fragile, n’est jamais exposé directement à Internet).
API Gateway : Nginx configuré comme passerelle d’API
Section titled “API Gateway : Nginx configuré comme passerelle d’API”Ce qu’une API Gateway ajoute par rapport à un simple reverse proxy
Section titled “Ce qu’une API Gateway ajoute par rapport à un simple reverse proxy”Un reverse proxy « nu » fait suivre une requête vers un backend. Une API Gateway est un reverse proxy à qui on a ajouté des responsabilités propres au monde des API :
- Authentification centralisée — vérifier une clé API, un JWT ou un token OAuth avant que la requête n’atteigne un microservice, pour que chaque microservice n’ait pas à réimplémenter cette vérification.
- Routage par chemin vers plusieurs microservices distincts — un point d’entrée unique (une seule URL publique) qui redistribue en interne vers N services indépendants.
- Limitation de débit (rate limiting) par client, pour protéger les backends contre un usage abusif.
- Souvent aussi : transformation de requêtes/réponses, agrégation de plusieurs appels, observabilité centralisée (métriques, traces) sur tout le trafic API.
Le montage : deux microservices, une seule porte d’entrée
Section titled “Le montage : deux microservices, une seule porte d’entrée”Deux applications Flask indépendantes :
catalogue-internesur127.0.0.1:5050(exposant/api/produits)commandessur127.0.0.1:5051(exposant/commandes)
Et une API Gateway Nginx sur le port 8082 qui centralise l’authentification par clé API, le routage, et la limitation de débit :
events {}http { limit_req_zone $http_x_api_key zone=par_client:10m rate=2r/s;
map $http_x_api_key $cle_valide { default 0; "cle-client-A" 1; }
server { listen 8082;
location /produits { if ($cle_valide = 0) { return 401; } limit_req zone=par_client burst=2 nodelay; rewrite ^/produits(.*)$ /api/produits$1 break; proxy_pass http://127.0.0.1:5050; add_header X-Gateway "api-gateway-nginx" always; add_header X-Route "service-catalogue" always; }
location /commandes { if ($cle_valide = 0) { return 401; } limit_req zone=par_client burst=2 nodelay; proxy_pass http://127.0.0.1:5051; add_header X-Gateway "api-gateway-nginx" always; add_header X-Route "service-commandes" always; } }}Test 1 — sans clé API, ou avec une clé invalide : refusé avant d’atteindre un microservice
Section titled “Test 1 — sans clé API, ou avec une clé invalide : refusé avant d’atteindre un microservice”$ curl -o /dev/null -w "HTTP %{http_code}\n" http://127.0.0.1:8082/produitsHTTP 401
$ curl -o /dev/null -w "HTTP %{http_code}\n" -H "X-Api-Key: cle-invalide" http://127.0.0.1:8082/produitsHTTP 401Ni catalogue-interne ni commandes n’ont reçu la moindre requête dans ce test — la gateway a coupé court avant de les solliciter.
Test 2 — avec la bonne clé, routage vers deux microservices différents
Section titled “Test 2 — avec la bonne clé, routage vers deux microservices différents”$ curl -D - -H "X-Api-Key: cle-client-A" http://127.0.0.1:8082/produitsHTTP/1.1 200 OKX-Gateway: api-gateway-nginxX-Route: service-catalogue{"produits":["clavier","souris","ecran"],"service":"catalogue-interne"}
$ curl -D - -H "X-Api-Key: cle-client-A" http://127.0.0.1:8082/commandesHTTP/1.1 200 OKX-Gateway: api-gateway-nginxX-Route: service-commandes{"commandes":[{"id":1,"statut":"expediee"}],"service":"commandes"}Même point d’entrée (8082), même clé — mais deux backends complètement distincts (5050 et 5051) répondent selon le chemin appelé. Le client n’a jamais eu besoin de connaître l’existence de deux services séparés.
Test 3 — limitation de débit, en conditions réelles
Section titled “Test 3 — limitation de débit, en conditions réelles”La zone limit_req_zone autorise 2 requêtes/seconde par clé API, avec une rafale (burst) de 2. Six requêtes envoyées le plus vite possible, avec la même clé :
Requête 1 -> HTTP 200Requête 2 -> HTTP 200Requête 3 -> HTTP 200Requête 4 -> HTTP 503Requête 5 -> HTTP 503Requête 6 -> HTTP 503Les 3 premières passent (le débit nominal plus la rafale absorbée), puis Nginx renvoie 503 sans même solliciter le backend — la protection contre les abus a bien lieu au niveau de la gateway, pas dans le code de chaque microservice.
Ce que ce test démontre
Section titled “Ce que ce test démontre”L’API Gateway a fait, dans ce seul montage, ce qu’un reverse proxy classique ne fait pas nativement : elle a authentifié la requête, l’a routée vers l’un de deux services indépendants selon le chemin, et a limité le débit par client — trois responsabilités transversales retirées des microservices eux-mêmes et centralisées à la frontière.
Tableau comparatif
Section titled “Tableau comparatif”| Critère | Forward proxy | Reverse proxy | API Gateway |
|---|---|---|---|
| Se place devant | Les clients | Les serveurs | Les serveurs (API) |
| Configuré par | Le client (ou son admin réseau) | L’opérateur du service | L’opérateur du service |
| Le client sait-il qu’il l’utilise ? | Oui, explicitement | Non, transparent | Non, transparent |
| Ce qu’il cache | L’identité/l’adresse du client | L’identité/la topologie du serveur | La topologie des microservices |
| Cas d’usage typique | Filtrage web d’entreprise, anonymisation, cache sortant | Répartition de charge, TLS, cache entrant | Auth centralisée, rate limiting, agrégation d’API |
| Exemple testé dans ce module | Squid (ACL client) | Nginx (masque un backend) | Nginx (auth + routage + rate limit) |
Les technologies : panorama
Section titled “Les technologies : panorama”| Techno | Type principal | Points forts | Limites | Licence |
|---|---|---|---|---|
| Nginx | Reverse proxy / LB / (gateway basique via modules) | Très répandu, léger, excellente doc, sert aussi de serveur web statique | Configuration déclarative peu flexible pour une logique métier complexe ; le vrai rate limiting/JWT avancé demande souvent des modules tiers ou OpenResty (Lua) | BSD (gratuit) |
| HAProxy | Reverse proxy / Load balancer | Référence historique du LB haute performance, algorithmes d’équilibrage très riches, observabilité fine (page de stats intégrée), excellent sous forte charge | Pas conçu pour la logique applicative niveau API (pas nativement JWT/OAuth) ; configuration orientée réseau plus que « API-first » | GPL/Open-source (+ version Enterprise payante) |
| Envoy | Proxy L4/L7 moderne, brique de service mesh | Observabilité de pointe (métriques, traces natives), conçu pour le cloud-native et Kubernetes, base d’Istio | Configuration très riche mais complexe à opérer seul (xDS, gRPC) — rarement utilisé “nu”, plutôt via Istio/Contour | Apache 2.0 (gratuit) |
| Traefik | Reverse proxy / API Gateway cloud-native | Auto-découverte des services (Docker, Kubernetes) sans redémarrage, dashboard intégré, Let’s Encrypt automatique | Écosystème de middlewares moins profond que Kong pour la gestion d’API métier (quotas avancés, monétisation) | MIT (+ version Enterprise) |
| Kong | API Gateway dédiée | Conçu spécifiquement pour les API (auth, quotas, plugins, portail développeur), écosystème de plugins très large | Empreinte plus lourde (base de données ou mode déclaratif à gérer), courbe d’apprentissage plus haute | Apache 2.0 (+ Enterprise) |
| Apache APISIX | API Gateway dédiée | Architecture plugin très performante (basée sur Nginx/OpenResty + etcd), riche en fonctionnalités API (gRPC, gRPC-Web, plugins natifs) | Communauté plus petite que Kong/Nginx, etcd ajoute une dépendance opérationnelle | Apache 2.0 (gratuit) |
| AWS API Gateway | API Gateway managée (cloud) | Zéro infrastructure à gérer, intégration native Lambda/IAM/Cognito, scaling automatique | Verrouillage fournisseur (vendor lock-in), coût à la requête qui peut grimper à fort volume, latence additionnelle par rapport à un gateway auto-hébergé | Propriétaire, payant à l’usage |
| Squid | Forward proxy | Le forward proxy open-source de référence depuis des décennies, cache HTTP mature, ACL très granulaires (testé dans ce module) | Pensé pour le trafic sortant client → Internet, pas pour exposer des services | GPL (gratuit) |
| Tinyproxy | Forward proxy léger | Empreinte mémoire minimale, configuration très simple | Beaucoup moins de fonctionnalités que Squid (pas de cache disque avancé, ACL plus basiques) | GPL (gratuit) |
Quel est le meilleur compromis ?
Section titled “Quel est le meilleur compromis ?”Il n’y a pas une seule bonne réponse indépendante du contexte — mais un compromis se dégage selon le besoin réel :
- Pour un simple reverse proxy / load balancer devant une application classique (le cas le plus fréquent en PME/ETI) : Nginx reste le meilleur compromis. Il est gratuit, extrêmement documenté, léger en ressources, et couvre 90 % des besoins (TLS, cache, répartition de charge, headers de sécurité) avec une configuration simple à auditer — comme démontré dans ce module et dans le Module 1. HAProxy reste préférable si la priorité absolue est la performance de répartition de charge à très haut débit avec des algorithmes fins (least-connections pondéré, sticky sessions avancées) et une observabilité réseau poussée.
- Pour une vraie API Gateway avec logique métier (authentification OAuth/JWT native, quotas par client, portail développeur, agrégation de plusieurs microservices) : Kong est le meilleur compromis dans la plupart des cas — il est open-source, bâti sur Nginx (donc performant et déjà connu de l’équipe), et son système de plugins couvre l’essentiel sans réinventer la roue. Traefik devient le meilleur choix si l’environnement est déjà conteneurisé (Docker/Kubernetes) et que la priorité est l’auto-découverte des services sans redéploiement manuel de configuration.
- Pour un environnement déjà entièrement sur AWS, où l’équipe ne veut gérer aucune infrastructure de gateway : AWS API Gateway est le meilleur compromis malgré le vendor lock-in, car le coût opérationnel économisé (pas de serveur à patcher, à scaler, à surveiller) dépasse souvent le surcoût à la requête pour des volumes modérés.
- Pour un forward proxy d’entreprise (filtrage et contrôle du trafic sortant des postes de travail) : Squid reste le standard le plus robuste et le plus testé en production, comme démontré plus haut avec les ACL.
Recommandation générale pour ce parcours : démarrer avec Nginx comme reverse proxy/gateway de base (déjà maîtrisé grâce aux modules précédents), puis migrer vers Kong seulement si des besoins spécifiquement « API management » apparaissent (quotas commerciaux, portail développeur, fédération d’authentification) — migrer trop tôt vers une gateway dédiée ajoute de la complexité opérationnelle avant qu’elle ne soit réellement nécessaire.
Ce que ce module ne couvre pas
Section titled “Ce que ce module ne couvre pas”Les tests ci-dessus utilisent une clé API statique en clair (map Nginx) pour rester lisibles pédagogiquement — une vraie API Gateway en production valide un JWT signé (voir le cours JWT de ce parcours) ou un token OAuth 2.0 (voir le cours OAuth) plutôt qu’une simple correspondance de chaîne. De même, la limitation de débit testée ici est locale à une seule instance Nginx — en production multi-instances, elle doit s’appuyer sur un compteur partagé (Redis) pour rester cohérente entre plusieurs répliques de la gateway.
Prochaine étape
Section titled “Prochaine étape”Réseaux cloud et Kubernetes : Services, Ingress et concepts réseau