GNU/Linux >> Tutoriels Linux >  >> Debian

Exécutez Apache, Nginx et HAProxy sur le même serveur (Debian, Ubuntu, CentOS)

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.

  1. Activer l'hôte SSL dans Apache ou Nginx avec un certificat auto-signé ou un certificat pour un autre domaine.
  2. 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.


Debian
  1. Comment installer Apache Hadoop sur CentOS 7, Ubuntu 18.04 et Debian 9

  2. Comment configurer le serveur DHCP sur CentOS 7 / Ubuntu 18.04 / 16.04 / Debian 9

  3. Comment installer Puppet 6.x sur Ubuntu 18.04 / Ubuntu 16.04 et Debian 9

  4. Debian – Comment exécuter des programmes 32 bits sur une Debian/ubuntu 64 bits ?

  5. Installer Apache sur CentOS 8

Comment installer Apache Maven sur Ubuntu 18.04 / Ubuntu 16.04 et Debian 9

Comment installer FileRun sur Ubuntu 20.04 avec Apache/Nginx

Installez Roundcube Webmail sur Ubuntu 18.04 avec Apache/Nginx

Installez Roundcube Webmail sur Ubuntu 20.04 avec Apache/Nginx

Comment installer InvoiceNinja sur le serveur Ubuntu 18.04 avec Apache/Nginx

Comment installer InvoiceNinja sur le serveur Ubuntu 20.04 avec Apache/Nginx