Reverse Proxy

ce majordome à votre service !

Nicolas Steinmetz / @nsteinmetz

Paris Web 2014

objectifs de cette conf

  • Démystifier les Reverse Proxy
  • Vous faire voir comment en tirer parti
  • Vous donner envie d'aller plus loin

(Reverse) Proxy ?

Mais de quoi tu me parles ?

Proxy

Forward Proxy

Intermédiaire entre des clients (PC/Serveurs) et d'autres ressources

  • Passerelle
  • Sécurité / Contrôle d'accès
  • Cache, Performance & Sauvegarde de bande passante
  • ...

Usage : interne vers externe

Attention au SPOF

PALC (Proxy à la C**)

Outil déployé dans les grands groupes pour accroître la productivité de leurs employés et de leurs coûteux prestataires

ou pas...

*Reverse* Proxy

ben un proxy, mais à l'envers !

Externe vers interne

Reverse Proxy
  • Passerelle
  • Sécurité / Contrôle d'accès
  • Cache, Performance & Sauvegarde de bande passante
  • Economie d'IPs publiques
  • ...

Attention au SPOF (aussi)

Mais pourquoi parler de Reverse Proxy à Paris Web ?

Changement de paradigme

  • Émergence de serveurs web alternatifs : nginx, lighttpd, etc
  • Généralisation des serveurs d'application
  • Séparation / répartition des rôles :
    • Principe de scalabilité
    • Le serveur web traite les fichiers statiques
    • Pour la partie dynamique, on "délègue" le traitement à un process distinct

Conclusion

Les reverse-proxys sont partout ; vous ne pouvez les ignorer !

Cas de départ

1 seul et unique serveur

  • Serveur Web : apache + mod_php
  • Base de données : *sql

Variante

2 serveurs

  • SRV1 : Serveur Web : apache + mod_php
  • SRV2 : Base de données

Rappel/info : par défaut, le traffic MySQL est en clair ; à sécuriser ?!

Usage 1 : Répartition de charge

  • 1 à n reverse-proxys
  • 1 à n frontaux

Mise en place du reverse proxy

Avec Apache + mod_proxy

                            
<VirtualHost *>                                
    ServerName www.exemple.com

    ProxyPreserveHost On
    ProxyPass / http://0.0.0.0:8080/
    ProxyPassReverse / http://0.0.0.0:8080/
</VirtualHost>

                        

Tout http://exemple.com/* sera rerouté vers votre application

Distribution par rôles

                            
<VirtualHost *>                                
    ServerName www.exemple.com

    ProxyPreserveHost On
    ProxyPass /docs http://docs.exemple.com/
    ProxyPass /backend http://backend.exemple.com/
    ProxyPass /static http://media.exemple.com/static/
    ProxyPass / http://main.exemple.com/

</VirtualHost>
                        

Suivant le chemin, votre RP va attaquer tel ou tel serveur pour le restituer au client

Multi-frontaux

Pré-requis :

  • Gestion des sessions,
  • Stockage accessible depuis chaque frontal,
  • ...

Attention aux choix/impacts infrastructuraux !!

Multi-frontaux

Avec apache + mod_proxy + mod_proxy_balancer

                            
<VirtualHost *>                                
    ServerName www.exemple.com

    ProxyPass / balancer://monApplication/
    <Proxy balancer://monApplication>
        BalancerMember http://1.2.3.4:8080
        BalancerMember http://1.2.3.5:8080
    </Proxy>
</VirtualHost>                  
                        

Multi-frontaux avec pondérations

                            
<VirtualHost *>                                
    ServerName www.exemple.com

    ProxyPass / balancer://monApplication/
    <Proxy balancer://monApplication>
        BalancerMember http://1.2.3.4:8080 loadfactor=1 timeout=10 retry=600
        BalancerMember http://1.2.3.5:8080 loadfactor=2 timeout=20 retry=600
        # La ligne suivante configure le serveur cible de réserve
        BalancerMember http://1.2.3.6:8080 status=+H
    </Proxy>                      
</VirtualHost>
                        

Pensez à personnaliser les pages d'erreurs 5xx !

Idem avec les erreurs 5xx

                            
<VirtualHost *>                                
    ServerName www.exemple.com

    <Location /misc/>
        ProxyPass http://localhost:8888/
        ProxyPassReverse http://localhost:8888/
    </Location>

    ErrorDocument 500 /misc/indisponible.html
    ErrorDocument 502 /misc/indisponible.html
    ErrorDocument 503 /misc/indisponible.html

    ProxyPass / balancer://monApplication/
    <Proxy balancer://monApplication>
        BalancerMember http://1.2.3.4:8080 loadfactor=1 timeout=10 retry=600
        BalancerMember http://1.2.3.5:8080 loadfactor=2 timeout=20 retry=600
        # La ligne suivante configure le serveur cible de réserve
        BalancerMember http://1.2.3.6:8080 status=+H
    </Proxy>
</VirtualHost>
                        

Là, c'est tout de suite la classe :-)

Usage 2 : Gestion des plages de maintenance

Ou l'effet : "l'Apple Store est fermé !!"

  • Rediriger les utilisateurs vers une page de maintenance
  • Autoriser les équipes techniques/fonctionnelles à finaliser/recetter le paramétrage du site en toute tranquilité

RewriteRulezzz

                            
<VirtualHost *>                                
    ServerName www.exemple.com

    RewriteEngine On                            
    # Tout ce qui ne provient pas de mon IP publique
    RewriteCond %{REMOTE_ADDR} !^111\.222\.111\.222
    # Et la même via un CDN
    RewriteCond %{HTTP:True-Client-IP} !^111\.222\.111\.222
    # Est redirigé vers une page de maintenance
    RewriteRule ^/(.*) http://www.domaine.tld/divers/maintenance.html [NE]
    # Donc moi, je passe :)

    ProxyPass / balancer://monApplication/
    <Proxy balancer://monApplication>
        BalancerMember http://1.2.3.4:8080 loadfactor=1 timeout=10 retry=600
        BalancerMember http://1.2.3.5:8080 loadfactor=2 timeout=20 retry=600
        # La ligne suivante configure le serveur cible de réserve
        BalancerMember http://1.2.3.6:8080 status=+H
    </Proxy>    
</VirtualHost>
                        

Usage 3 : Reverse Proxy SSL

Principe

  • Le traffic entre l'utilisateur et le reverse proxy est chiffré
  • Le traffic entre le reverse proxy et les frontaux est en http / https

Avantages

  • Réduction du coût de certificat (1 par RP et non 1 / frontal)
  • Économie d'IPs publiques
  • Limiter le chiffrement à la partie indispensable

!! Le traffic en clair ne peut se faire qu'au sein d'un LAN - jamais entre des machines sur un réseau public !

Côté http, redirection intelligente vers https

                            
<VirtualHost *>                                
    ServerName www.exemple.com

    # Redirection de /inscription/* et /moncompte/* vers l'url en https
    RewriteRule ^/(inscription/.*) https://ssl.domaine.tld/$1 [NE]
    RewriteRule ^/(moncompte/.*) https://ssl.domaine.tld/$1 [NE]
    # Pour le reste, rester en http simple
    RewriteRule ^/(.*)$ balancer://monApplication%{REQUEST_URI} [NE,P,L]

    <Proxy balancer://monApplication>
        BalancerMember http://1.2.3.4:8080 loadfactor=1 timeout=10 retry=600
        BalancerMember http://1.2.3.5:8080 loadfactor=2 timeout=20 retry=600
        # La ligne suivante configure le serveur cible de réserve
        BalancerMember http://1.2.3.6:8080 status=+H
    </Proxy>
</VirtualHost>                  
                        

... et côté https

                            
<VirtualHost *:443>                                
    ServerName www.exemple.com

    # Maintient de /inscription/* et /moncompte/* vers mon cluster de frontaux
    RewriteRule ^/(inscription/.*) balancer://monApplication%{REQUEST_URI} [NE,P,L]
    RewriteRule ^/(moncompte/.*) balancer://monApplication%{REQUEST_URI} [NE,P,L]
    # Pour le reste, revenir en http simple
    RewriteRule ^/(.*)$ http://www.domaine.tld/$1 [NE]

    <Proxy balancer://monApplication>
        BalancerMember http://1.2.3.4:8080 loadfactor=1 timeout=10 retry=600
        BalancerMember http://1.2.3.5:8080 loadfactor=2 timeout=20 retry=600
        # La ligne suivante configure le serveur cible de réserve
        BalancerMember http://1.2.3.6:8080 status=+H
    </Proxy>
</VirtualHost>                      
                        

Bonus : full https (avec mod_ssl)

                            
<VirtualHost *:443>                                
    ServerName www.exemple.com

    SSLProxyEngine on # Enable SSL Proxy
    SSLProxyCheckPeerCN on # Check if remote certificate is valid
    SSLProxyCheckPeerExpire on # Check if remote certificate is expired

    ProxyPass / balancer://monApplication/
    <Proxy balancer://monApplication>
        BalancerMember https://1.2.3.4:8080 loadfactor=1 timeout=10 retry=600
        BalancerMember https://1.2.3.5:8080 loadfactor=2 timeout=20 retry=600
        # La ligne suivante configure le serveur cible de réserve
        BalancerMember https://1.2.3.6:8080 status=+H
    </Proxy>
</VirtualHost>
                        

Le certificat du frontal n'a pas besoin d'être signé publiquement ; il faut juste que le RP puisse le valider

Usage 4 : Contourner la Same Origin Policy

Quand CORS et CSP ne peuvent pas être utilisés

                            
location /ressource_externe {
    proxy_pass http://www.partenaire.com/contenu/a/recuperer;
}
                            
                        

À utiliser en dernier recours

Usage 5 : Sécurité

  • Ne passe le reverse proxy que ce qui a été autorisé
  • Mise en place de pare-feu applicatif (WAF) : mod_security, naxsi (nginx), etc.
  • Limite la surface d'attaque de son réseau

Exemple basique

(mais parfois suffisant)

                            
<VirtualHost *>                                
    ServerName www.exemple.com

    ProxyPreserveHost On
    ProxyPass /app/ http://app.exemple.com/
    ProxyPass /backend http://backend.exemple.com/
    ProxyPass /static http://media.exemple.com/static/

</VirtualHost>
                        

Dans ce cas /admin/ n'est pas accessible via votre RP mais peut l'être depuis votre LAN par exemple.

Usage 6 : Cache

Ton serveur applicatif point trop tu ne solliciteras

Cache sur disque/RAM

Attention aux stratégites d'invalidation du cache et leurs effets en terme de (contre-)performance

Usage 7 : Réécriture du html à la volée

  • Une application hébergé dans un LAN UK : "myblog.uk.myfirm.lan"
  • Les utilisateurs France ne résolvent pas *.uk.myfirm.lan mais uniquement *.fr.macompagnie.lan
  • Le Reverse Proxy sur le LAN France a accès au serveur UK

Facile !

    
<VirtualHost 1.2.3.4:80>
        ServerName  blog-uk.fr.macompagnie.lan  
      
        ProxyPreserveHost On  
        RequestHeader set Host: myblog.uk.myfirm.lan 
        ProxyPass / http://1.1.1.1/  
        ProxyPassReverse / http://1.1.1.1/  
</VirtualHost>  

Sauf que les liens du site sont absolus ! #paf

Enter mod_substitute


<VirtualHost 1.2.3.4:80>
    ServerName  blog-uk.fr.macompagnie.lan   

    ProxyPreserveHost On  
    RequestHeader set Host: myblog.uk.myfirm.lan 
    ProxyPass / http://1.1.1.1/  
    ProxyPassReverse / http://1.1.1.1/  
  
    <IfModule mod_substitude.so>  
        AddOutputFilterByType SUBSTITUTE text/html  
        Substitute s/myblog.uk.myfirm.lan/blog-uk.fr.macompagnie.lan/iq  
        SetOutputFilter INFLATE;SUBSTITUTE;DEFLATE  
    </IfModule>

</VirtualHost>    

#MasterOfUniverse

Pour Apache 2.4, il y a aussi mod_proxy_html

Attention au SPOF

Ta résilience tu travailleras

Implémenter un RP avec un site existant ?

En mode mono-serveur :

  • Mettre votre RP sur un port exotique (81, 8080, 8888)
  • Recetter le bon fonctionnement de votre application via le RP
  • Inverser le port entre votre RP et serveur web

En mode multi-serveurs :

  • Mettre votre rp sur une url exotique : rp.exemple.com
  • Recetter le bon fonctionnement de votre application via le RP
  • Mettre le domaine principal sur le RP en lieu et place du serveur web

Aller plus loin

 

 

Mais commencez *simple* !

Et encore plus loin

L'année prochaine, *tu* présentes quoi à Paris-Web ?

Parce que moi aussi l'année dernière, j'étais à ta place...

Merci !

Crédits