Si vous êtes un administrateur de serveur, vous avez probablement un serveur Web de votre choix comme Apache ou Nginx. Apache est un serveur Web bien connu depuis les années 1990. Nginx a été développé pour la première fois en 2004 et a rapidement gagné du terrain en raison de sa faible empreinte mémoire et de sa vitesse de traitement rapide pour les fichiers HTML statiques.
Apache et Nginx prennent tous deux en charge l'hébergement virtuel, ce qui signifie que vous pouvez héberger plusieurs sites Web ou applications Web sur le même serveur. Cependant, vous rencontrerez des situations dans lesquelles vous avez un serveur Web existant en cours d'exécution, mais une application Web particulière nécessite l'utilisation d'un serveur Web différent. Le port 80 ou 443 sur l'adresse IP publique ne peut être utilisé que par un seul processus. Si Apache utilise le port, Nginx ne peut pas l'utiliser (ou s'y lier). Alors que pouvez-vous faire ?
Vous pouvez configurer Nginx en tant que proxy inverse vers Apache, afin que Nginx puisse rediriger les requêtes HTTP vers Apache. D'après mon expérience, j'ai trouvé que ce n'est pas toujours la meilleure solution car cela a déjà causé des problèmes étranges que je ne peux pas résoudre. Au lieu de cela, je préfère utiliser HAProxy comme proxy inverse pour Nginx et Apache . HAProxy est un équilibreur de charge et un serveur proxy gratuits et open source à haute disponibilité pour les applications TCP et HTTP.
Exécutez Apache, Nginx et HAProxy sur le même serveur
Voici comment cela fonctionne.
- Nginx écoute sur 127.0.0.1:80 et 127.0.0.1:443
- Apache écoute sur 127.0.0.2:80 et 127.0.0.2:443
- HAProxy écoute sur les ports 80 et 443 de l'adresse IP publique. Il redirige la requête HTTP sur le port 80 vers le port 443. Lorsqu'une requête arrive sur le port 443, il choisira entre le back-end Nginx et Apache en analysant l'en-tête SNI (indication du nom du serveur) dans la requête HTTPS.
En fait, Cloudflare (un fournisseur de CDN) utilise également l'en-tête SNI pour déterminer comment acheminer les requêtes HTTPS vers les serveurs d'origine.
Étape 1 :Arrêtez Nginx et Apache
Pour arrêter Nginx sur Debian, Ubuntu et CentOS, exécutez
sudo systemctl stop nginx
Pour arrêter Apache sur Debian/Ubuntu, exécutez
sudo systemctl stop apache2
Pour arrêter Apache sur CentOS, exécutez
sudo systemctl stop httpd
Étape 2 :Modifier le port d'écoute dans Nginx
Nous devons faire écouter Nginx sur 127.0.0.1:80. Ouvrez vos fichiers de configuration Nginx dans /etc/nginx/conf.d/
ou /etc/nginx/sites-enabled/
et trouvez la ligne suivante.
listen 80;
Changez-le en
listen 127.0.0.1:80;
Si https est activé sur le bloc de serveur Nginx, recherchez également
listen 443 ssl;
Et changez-le en
listen 127.0.0.1:443 ssl;
Le fichier de configuration principal de Nginx /etc/nginx/nginx.conf
peut inclure un hôte virtuel par défaut écoutant sur le port 80 ou 443, vous devrez donc peut-être également modifier ce fichier.
Redémarrez Nginx pour que les modifications prennent effet.
sudo systemctl restart nginx
Étape 3 :Modifier le port d'écoute dans Apache
Nous devons faire en sorte qu'Apache écoute sur 127.0.0.2:80.
Debian/Ubuntu
Sur Debian et Ubuntu, modifiez le /etc/apache2/ports.conf
fichier.
sudo nano /etc/apache2/ports.conf
Modifier
Listen 80 Listen 443
À
Listen 127.0.0.2:80 Listen 127.0.0.2:443
Enregistrez et fermez le fichier. Allez aussi dans /etc/apache2/sites-enabled/
répertoire, modifiez les fichiers de l'hôte virtuel. Modifier
<VirtualHost *:80>
À
<VirtualHost 127.0.0.2:80>
S'il existe un hôte virtuel SSL, modifiez également
<VirtualHost *:443>
À
<VirtualHost 127.0.0.2:443>
Redémarrez Apache.
sudo systemctl restart apache2
CentOS
Sur CentOS, modifiez le /etc/httpd/conf/httpd.conf
fichier.
sudo nano /etc/httpd/conf/httpd.conf
Trouver
Listen 80
Changez-le en
Listen 127.0.0.2:80
Enregistrez et fermez le fichier. Allez ensuite dans /etc/httpd/conf.d/
répertoire, modifiez les fichiers de l'hôte virtuel. Modifier
<VirtualHost *:80>
À
<VirtualHost 127.0.0.2:80>
S'il existe un hôte virtuel SSL, modifiez également
<VirtualHost *:443>
À
<VirtualHost 127.0.0.2:443>
Dans le /etc/httpd/conf.d/ssl.conf
fichier, il y a
Listen 443 https
Changez-le en :
Listen 127.0.0.2:443 https
Enregistrez et fermez le fichier. Redémarrez Apache pour que les modifications prennent effet.
sudo systemctl restart httpd
Étape 4 :Configurer HAProxy
Installez HAProxy sur votre distribution.
Debian/Ubuntu
sudo apt install haproxy
CentOS
sudo dnf install haproxy
Modifier le fichier de configuration HAProxy.
sudo nano /etc/haproxy/haproxy.cfg
Ajoutez l'extrait de code suivant à la fin du fichier, ce qui permettra à HAPorxy d'écouter sur le port 80 de l'adresse IP publique et de rediriger les requêtes HTTP sur le port 80 vers le port 443. Remplacez 12.34.56.78 par l'adresse IP publique de votre serveur.
frontend http bind 12.34.56.78:80 mode http redirect scheme https code 301
Maintenant, nous devons également ajouter un frontal HTTPS.
frontend https bind 12.34.56.78:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 }
Définissez ensuite les back-ends Nginx et Apache. La check
Le paramètre indique à HAProxy d'effectuer des vérifications de l'état du back-end en envoyant un paquet TCP.
backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check
Vous pouvez définir un backend par défaut avec :
default_backend nginx
Nous utiliserons l'en-tête SNI dans la requête HTTPS pour rediriger vers le bon back-end. Par exemple, si Nginx sert domain1.com
et Apache sert domain2.com
, puis vous ajoutez les deux lignes suivantes. Vous pouvez également utiliser des sous-domaines, tant qu'ils sont différents.
use_backend nginx if { req_ssl_sni -i domain1.com } use_backend apache if { req_ssl_sni -i domain2.com }
Notez que le default_backend
et use_backend
les directives doivent être placées au-dessus des définitions du backend.
frontend http bind 12.34.56.78:80 mode http redirect scheme https code 301 frontend https bind 12.34.56.78:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } default_backend nginx use_backend nginx if { req_ssl_sni -i domain1.com } use_backend apache if { req_ssl_sni -i domain2.com } backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check
Dans la configuration ci-dessus, nous avons utilisé la fonctionnalité SNI (Server Name Indication) dans TLS pour différencier le trafic HTTPS.
- Lorsque domain1.com est dans le client TLS Hello, HAProxy redirige le trafic vers le
nginx
back-end. - Lorsque domain2.com est dans le client TLS Hello, HAProxy redirige le trafic vers
apache
back-end.
Si le client ne spécifie pas le nom du serveur dans TLS Client Hello, alors HAproxy utilisera le backend par défaut (nginx).
Enregistrez et fermez le fichier. Puis redémarrez HAproxy.
sudo systemctl restart haproxy
Désormais, Apache, Nginx et HAProxy peuvent s'exécuter sur le même serveur.
Comment transférer l'adresse IP du client vers le backend
Par défaut, Apache et Nginx ne peuvent voir que l'adresse IP de HAProxy. Pour obtenir la véritable adresse IP du client, assurez-vous d'avoir ajouté le send-proxy-v2
option dans la définition du back-end HAProxy comme ci-dessous.
backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 send-proxy-v2 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 send-proxy-v2 check
Nous devons également ajouter une configuration dans Nginx et Apache pour que cela fonctionne, sinon votre site Web sera inaccessible.
Nginx
Ajouter proxy_protocol
dans le Nginx listen
directive comme ci-dessous.
listen 127.0.0.2:443 ssl http2 proxy_protocol;
Ajoutez ensuite les deux directives suivantes dans le Nginx http { }
bloquer dans /etc/nginx/nginx.conf
fichier.
set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol;
Enregistrez et fermez le fichier. Rechargez ensuite Nginx.
sudo systemctl reload nginx
Remarque :Si votre site Web s'exécute derrière Cloudflare CDN, vous devez modifier real_ip_header proxy_protocol;
à real_ip_header CF-Connecting-IP;
afin d'afficher la véritable adresse IP du client. Vous pouvez également ajouter ce real_ip_header
directive au fichier de bloc de serveur individuel pour remplacer la configuration globale dans /etc/nginx/nginx.conf
fichier.
Enfin, redémarrez HAProxy.
sudo systemctl restart haproxy
Apache
Si vous utilisez Apache sur Debian/Ubuntu, vous devez activer le remoteip module. (Ce module est activé sur CentOS par défaut.)
sudo a2enmod remoteip
Ajoutez ensuite les 3 lignes suivantes dans votre fichier de configuration d'hôte virtuel Apache.
RemoteIPProxyProtocol On RemoteIPHeader X-Forwarded-For RemoteIPTrustedProxy 127.0.0.1
Comme ça.
<VirtualHost 127.0.0.2:443> ServerName www.example.com RemoteIPProxyProtocol On RemoteIPHeader X-Forwarded-For RemoteIPTrustedProxy 127.0.0.1
Enregistrez et fermez le fichier. Ensuite, nous devons également modifier le combined
format de journal. Modifiez le fichier de configuration principal d'Apache.
sudo nano /etc/apache2/apache2.conf
ou
sudo nano /etc/httpd/conf/httpd.conf
Trouvez la ligne suivante.
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
Remplacez-le par :
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
Enregistrez et fermez le fichier. Redémarrez ensuite Apache pour que les modifications prennent effet.
sudo systemctl restart apache2
ou
sudo systemctl restart httpd
Remarque que le RemoteIPProxyProtocol On
est uniquement disponible dans Apache 2.4.31 et versions ultérieures. Pour vérifier votre version d'Apache, exécutez
sudo apache2 -v
ou
sudo httpd -v
Ubuntu 18.04 est livré avec Apache 2.4.29. Si votre version d'Apache ne répond pas à cette exigence, vous devez supprimer le send-proxy-v2
dans la définition de serveur principal HAProxy. CentOS 8 est livré avec Apache 2.4.37.
Enfin, redémarrez HAProxy.
sudo systemctl restart haproxy
Comment ajouter de nouveaux hôtes virtuels
Si vous avez des serveurs Web Apache et Nginx, vous n'avez besoin que de deux backends :un pour Apache et un pour Nginx.
Lorsque vous devez ajouter un autre domaine (ou sous-domaine), vous n'avez pas besoin d'ajouter un nouveau backend dans HAProxy. Au lieu de cela, vous devez créer un nouvel hôte virtuel pour le nouveau domaine (ou sous-domaine) dans Apache ou Nginx, puis utiliser le use_backend
directive dans HAProxy pour rediriger le trafic vers le bon backend.
frontend http bind 12.34.56.78:80 mode http redirect scheme https code 301 frontend https bind 12.34.56.78:443 mode tcp tcp-request inspect-delay 5s tcp-request content accept if { req_ssl_hello_type 1 } default_backend nginx use_backend nginx if { req_ssl_sni -i domain1.com } use_backend nginx if { req_ssl_sni -i sub.domain1.com } use_backend apache if { req_ssl_sni -i domain2.com } use_backend apache if { req_ssl_sni -i sub.domain2.com } backend nginx mode tcp option ssl-hello-chk server nginx 127.0.0.1:443 check backend apache mode tcp option ssl-hello-chk server apache 127.0.0.2:443 check
Je recommande d'utiliser apache
et nginx
comme les noms de backend comme dans le code ci-dessus, vous savez donc quel serveur Web héberge quelle application.
Obtenir un nouveau certificat SSL Let's Encrypt
Défi http-01
Tout d'abord, vous devez comprendre comment utiliser l'authentificateur Certbot apache et nginx pour obtenir un certificat TLS.
- Activer correctement HTTPS sur Apache avec Let's Encrypt sur Ubuntu
- Activer correctement HTTPS sur Nginx avec Let's Encrypt sur Ubuntu
L'authentificateur Certbot apache et nginx utilise http-01
défi, qui fonctionne sur le port TCP 80. Étant donné que HAProxy utilise le port TCP 80, le Certbot http-01
défi est susceptible d'échouer. Cependant, vous pouvez le faire fonctionner avec la méthode suivante.
- Activer l'hôte SSL dans Apache ou Nginx avec un certificat auto-signé ou un certificat pour un autre domaine.
- Utilisez ensuite l'authentificateur Certbot apache et nginx comme d'habitude.
Cette méthode fonctionne car le Certbot http-01
le défi peut être redirigé du port TCP 80 vers le port TCP 443, et Certbot accepte les certificats non valides sur le port 443.
Défi DNS-01
Vous pouvez également utiliser le certbot dns-01
défi, qui fonctionne en créant un enregistrement TXT temporaire pour votre domaine pour certifier que vous possédez réellement ce domaine, afin qu'il puisse contourner le port TCP 80 et le port TCP 443. L'inconvénient de cette méthode est que tous les bureaux d'enregistrement de domaine ne sont pas pris en charge.
Tout d'abord, vous devez installer le plugin DNS Certbot. Ce sont plusieurs plugins DNS disponibles dans le référentiel de logiciels Debian et Ubuntu, que vous pouvez trouver avec
apt search python3-certbot-dns
Sortie :
python3-certbot-dns-cloudflare/bionic,bionic 0.23.0-1 all Cloudflare DNS plugin for Certbot python3-certbot-dns-digitalocean/bionic,bionic 0.23.0-1 all DigitalOcean DNS plugin for Certbot python3-certbot-dns-dnsimple/bionic,bionic 0.23.0-1 all DNSimple DNS plugin for Certbot python3-certbot-dns-google/bionic,bionic 0.23.0-1 all Google DNS plugin for Certbot python3-certbot-dns-rfc2136/bionic,bionic 0.23.0-1 all RFC 2136 DNS plugin for Certbot python3-certbot-dns-route53/bionic,bionic 0.23.0-1 all Route53 DNS plugin for Certbot
Sur CentOS 8, vous pouvez trouver des plugins DNS Certbot à partir du référentiel EPEL. Notez que vous devez installer Certbot à partir du référentiel CentOS par défaut.
sudo dnf install certbot
Trouvez des plugins DNS dans le référentiel EPEL.
sudo dnf install epel-release dnf search certbot-dns
Sortie :
python3-certbot-dns-ovh.noarch : OVH DNS Authenticator plugin for Certbot python3-certbot-dns-nsone.noarch : NS1 DNS Authenticator plugin for Certbot python3-certbot-dns-gehirn.noarch : Gehirn Infrastructure Service DNS Authenticator plugin for Certbot python3-certbot-dns-google.noarch : Google Cloud DNS Authenticator plugin for Certbot python3-certbot-dns-linode.noarch : Linode DNS Authenticator plugin for Certbot python3-certbot-dns-luadns.noarch : LuaDNS Authenticator plugin for Certbot python3-certbot-dns-rfc2136.noarch : RFC 2136 DNS Authenticator plugin for Certbot python3-certbot-dns-route53.noarch : Route53 DNS Authenticator plugin for Certbot python3-certbot-dns-cloudxns.noarch : CloudXNS DNS Authenticator plugin for Certbot python3-certbot-dns-dnsimple.noarch : DNSimple DNS Authenticator plugin for Certbot python3-certbot-dns-cloudflare.noarch : Cloudflare DNS Authenticator plugin for Certbot python3-certbot-dns-cloudflare.noarch : Cloudflare DNS Authenticator plugin for Certbot python3-certbot-dns-dnsmadeeasy.noarch : DNS Made Easy DNS Authenticator plugin for Certbot python3-certbot-dns-sakuracloud.noarch : Sakura Cloud DNS Authenticator plugin for Certbot
Installez l'un de ces plugins en fonction du service d'hébergement DNS que vous utilisez. J'utilise Cloudflare, je vais donc utiliser Cloudflare comme exemple. Exécutez la commande suivante pour installer le python3-certbot-dns-cloudflare
paquet sur Debian/Ubuntu.
sudo apt install python3-certbot-dns-cloudflare
Créez ensuite un fichier de configuration pour Cloudflare.
sudo nano /etc/letsencrypt/cloudflare.ini
Nous devons ajouter l'adresse e-mail et la clé API de notre compte Cloudflare dans ce fichier.
# Cloudflare API credentials used by Certbot dns_cloudflare_email = [email protected] dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567
Vous pouvez trouver votre clé API Cloudflare sur https://dash.cloudflare.com/profile
. Notez que le plug-in Certbot Cloudflare ne prend actuellement pas en charge les « jetons API » de Cloudflare, alors assurez-vous d'utiliser la « clé API globale » pour l'authentification.
Enregistrez et fermez le fichier. La clé API contourne l'authentification à deux facteurs de Cloudflare, vous ne devez donc autoriser que l'utilisateur root à lire ce fichier.
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
Exécutez maintenant certbot.
sudo certbot --agree-tos -a dns-cloudflare -i nginx --redirect --hsts --staple-ocsp --email [email protected] -d www.your-domain.com,your-domain.com
Dans la commande ci-dessus, nous avons spécifié que nous utiliserons dns-cloudflare
en tant qu'authentificateur pour obtenir un nouveau certificat TLS et utiliser le nginx
plugin pour créer le bloc serveur HTTPS. Si vous utilisez Apache, remplacez alors nginx
avec apache
.
Cette commande vous demandera de saisir le chemin du .ini
fichier, alors entrez /etc/letsencrypt/cloudflare.ini
et appuyez sur la touche Entrée.
Une fois le certificat SSL obtenu et installé dans le fichier de configuration du serveur Web. Vous devez le faire écouter sur 127.0.0.1:443 ou 127.0.0.2:443. Par exemple, si vous utilisez Nginx, recherchez
listen 443 ssl
Et changez-le en
listen 127.0.0.1:443 ssl http2
Changez également le port 80 en
listen 127.0.0.1:80;
Enregistrez et fermez le fichier. Redémarrez ensuite votre serveur Web.
Erreurs courantes
1 mauvais nom de domaine
Si vous avez plusieurs hôtes virtuels Nginx sur un serveur et que lorsque vous tapez un nom de domaine, le navigateur Web vous amène à un autre nom de domaine hébergé sur le même serveur, il se peut que l'un de vos noms de fichier d'hôte virtuel Nginx ne se termine pas avec le .conf
extension de nom de fichier, donc Nginx n'a pas chargé cet hôte virtuel. Il se peut également que vous ayez défini un enregistrement AAAA pour le nom de domaine, mais que vous n'ayez pas configuré Nginx pour servir le nom de domaine en IPv6.
Ce qui précède s'applique également au serveur Web Apache.
2 Violation du protocole réseau
Si vous définissez le send-proxy-v2
header dans HAProxy, mais n'a pas activé proxy_protocol
dans Nginx ou Apache, votre site Web affichera l'erreur suivante.
The site has experienced a network protocol violation that cannot be repaired.
N'oubliez pas de redémarrer Nginx/Apache après avoir apporté des modifications au fichier de configuration.
3 PR_CONNECT_RESET_ERROR
Si vous activez proxy_protocol
dans Nginx ou Apache, mais n'a pas défini le send-proxy-v2
header dans HAProxy, votre site Web affichera cette erreur.
secure connection failed. PR_CONNECT_RESET_ERROR
Et vous trouverez le message d'erreur suivant dans le journal des erreurs Nginx ou Apache.
broken header while reading PROXY protocol
N'oubliez pas de redémarrer Nginx/Apache après avoir apporté des modifications au fichier de configuration.
Notez également que si vous activez le proxy protocol
dans un fichier d'hôte virtuel Apache/Nginx, il est également implicitement activé pour tous les autres hôtes virtuels. Et je n'ai pas trouvé de moyen de désactiver proxy_protocol
pour un hôte virtuel individuel. Étant donné que vous exécutez Apache et Nginx sur le même serveur, une solution de contournement consiste à activer uniquement le protocole proxy dans Nginx et à ne pas l'activer dans Apache. Si un hôte virtuel n'a pas besoin d'obtenir la véritable adresse IP du client, configurez-le pour utiliser Apache.
Mettre à jour :Il m'est venu à l'esprit que vous pouvez configurer un nouvel hôte virtuel Apache/Nginx sur une autre adresse de bouclage comme 127.0.0.4. De cette façon, le nouvel hôte virtuel n'activera pas le protocole proxy.
4 PR_END_OF_FILE_ERROR
Si vous avez activé le protocole proxy dans Apache/Nginx, mais que vous essayez d'accéder directement à l'hôte virtuel (en contournant HAProxy), vous verrez l'erreur suivante.
PR_END_OF_FILE_ERROR
5 SSL_ERROR_SYSCALL
Si vous utilisez la commande curl :
curl -I https://example.com
Et vous rencontrez l'erreur suivante
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to example.com:443
C'est probablement parce que vous n'avez pas défini de définition de backend pour ce domaine.