Aller au contenu

Apache : reverse proxy

Un reverse proxy transmet les requêtes des visiteurs à une application qui écoute sur un port local. Il gère aussi HTTPS et la sécurité. Les exemples utilisent une application fictive sur 127.0.0.1:3000.

Fenêtre de terminal
sudo a2enmod proxy proxy_http headers
sudo systemctl restart apache2
Module Rôle
proxy Cœur du proxy
proxy_http Proxy HTTP et HTTPS
proxy_wstunnel WebSockets
proxy_balancer, lbmethod_byrequests Répartition de charge
headers Modification des en-têtes
remoteip Adresse réelle du client derrière un autre proxy
<VirtualHost *:80>
ServerName app.exemple.com
ProxyRequests Off
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
RequestHeader set X-Forwarded-Proto "http"
</VirtualHost>
Directive Rôle
ProxyRequests Off Désactive le proxy direct (mandataire ouvert) : toujours à Off pour un reverse proxy
ProxyPreserveHost On Transmet le Host demandé par le visiteur à l’application
ProxyPass Transmet les requêtes du chemin vers l’application
ProxyPassReverse Réécrit les redirections (Location) renvoyées par l’application
RequestHeader set X-Forwarded-Proto Indique le protocole d’origine (https derrière TLS)

Apache ajoute automatiquement X-Forwarded-For (adresse du visiteur), X-Forwarded-Host et X-Forwarded-Server.

Derrière HTTPS, remplacer l’en-tête par :

RequestHeader set X-Forwarded-Proto "https"
Écriture Requête /api/utilisateurs transmise comme
ProxyPass /api/ http://127.0.0.1:4000/ /utilisateurs (le préfixe /api/ est retiré)
ProxyPass /api/ http://127.0.0.1:4000/api/ /api/utilisateurs (chemin conservé)
ProxyPass /api/ http://127.0.0.1:4000/
ProxyPassReverse /api/ http://127.0.0.1:4000/

Garder la même forme (avec ou sans / final) des deux côtés de ProxyPass.

DocumentRoot /var/www/exemple.com
ProxyPass /api/ http://127.0.0.1:4000/
ProxyPassReverse /api/ http://127.0.0.1:4000/
ProxyPass /statique ! # exclu du proxy : servi par Apache

Les règles ProxyPass sont évaluées dans l’ordre d’écriture : placer les exceptions (!) avant les règles générales.

Fenêtre de terminal
sudo a2enmod proxy_wstunnel rewrite
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/ws/(.*)$ ws://127.0.0.1:3000/ws/$1 [P,L]
ProxyPass /ws/ http://127.0.0.1:3000/ws/
ProxyPassReverse /ws/ http://127.0.0.1:3000/ws/

Pour un chemin entièrement WebSocket, la forme courte suffit : ProxyPass "/ws/" "ws://127.0.0.1:3000/ws/".

ProxyPass /evenements http://127.0.0.1:3000/evenements flushpackets=on

flushpackets=on transmet les données dès leur réception, sans mise en mémoire tampon.

ProxyTimeout 60 # délai global d'attente de l'application
ProxyPass / http://127.0.0.1:3000/ timeout=120 connectiontimeout=5 retry=0
LimitRequestBody 20971520 # taille maximale du corps de requête : 20 Mo
Fenêtre de terminal
sudo a2enmod proxy_balancer lbmethod_byrequests
<Proxy "balancer://application">
BalancerMember http://127.0.0.1:3000 retry=30
BalancerMember http://127.0.0.1:3001 retry=30
BalancerMember http://127.0.0.1:3002 status=+H # de secours (« hot standby »)
ProxySet lbmethod=byrequests
</Proxy>
ProxyPass / balancer://application/
ProxyPassReverse / balancer://application/
Méthode (lbmethod) Comportement
byrequests Répartition selon le nombre de requêtes (défaut)
bytraffic Répartition selon le volume transféré (module lbmethod_bytraffic)
bybusyness Vers le membre le moins occupé (module lbmethod_bybusyness)

Un membre en échec est retiré pendant retry secondes.

Adresse réelle du visiteur derrière un autre proxy

Section intitulée « Adresse réelle du visiteur derrière un autre proxy »

Si Apache est lui-même derrière un répartiteur de charge ou un CDN :

Fenêtre de terminal
sudo a2enmod remoteip
RemoteIPHeader X-Forwarded-For
RemoteIPInternalProxy 10.0.0.0/8

Apache remplace alors l’adresse du client dans les journaux et les règles Require ip.

SSLProxyEngine On # nécessite le module ssl
ProxyPass / https://127.0.0.1:8443/
ProxyPassReverse / https://127.0.0.1:8443/

Éviter SSLProxyVerify none en production : il désactive la vérification du certificat de l’application.

Fenêtre de terminal
curl -I http://app.exemple.com/
curl -H "Host: app.exemple.com" http://127.0.0.1/
sudo apache2ctl -S
sudo tail -f /var/log/apache2/error.log
Symptôme Piste
Invalid command 'ProxyPass' sudo a2enmod proxy proxy_http puis redémarrer
503 Service Unavailable L’application est arrêtée ou injoignable : curl http://127.0.0.1:3000. Apache met le membre en erreur pendant retry secondes
502 Bad Gateway L’application ferme la connexion ou répond de façon invalide
504 Gateway Timeout Application trop lente : augmenter ProxyTimeout ou timeout=
AH01114: HTTP: failed to make connection to backend Mauvais port ou application arrêtée
Redirections vers http://127.0.0.1:3000/… ProxyPassReverse manquant ou différent de ProxyPass
Liens générés en http:// Transmettre X-Forwarded-Proto et configurer l’application
WebSocket qui se coupe proxy_wstunnel activé, règles RewriteRule … [P] et ProxyTimeout assez long

Ubuntu 24.04 et 26.04 : différences à connaître

Section intitulée « Ubuntu 24.04 et 26.04 : différences à connaître »

Les directives de proxy sont identiques sur Apache 2.4.58 (24.04) et 2.4.66 (26.04).