Wenn Sie ein Serveradministrator sind, haben Sie wahrscheinlich einen Webserver Ihrer Wahl wie Apache oder Nginx. Apache ist seit den 1990er Jahren ein bekannter Webserver. Nginx wurde erstmals im Jahr 2004 entwickelt und hat sich aufgrund seines geringen Speicherverbrauchs und der schnellen Verarbeitungsgeschwindigkeit für statische HTML-Dateien schnell durchgesetzt.
Sowohl Apache als auch Nginx unterstützen virtuelles Hosting, was bedeutet, dass Sie mehrere Websites oder Webanwendungen auf demselben Server hosten können. Sie werden jedoch auf Situationen stoßen, in denen Sie einen vorhandenen Webserver ausführen, aber eine bestimmte Webanwendung die Verwendung eines anderen Webservers erfordert. Port 80 oder 443 auf der öffentlichen IP-Adresse kann nur von einem Prozess verwendet werden. Wenn Apache den Port verwendet, kann Nginx ihn nicht verwenden (oder daran binden). Was können Sie also tun?
Sie können Nginx als Reverse-Proxy für Apache konfigurieren, sodass Nginx HTTP-Anforderungen an Apache umleiten kann. Nach meiner Erfahrung habe ich festgestellt, dass dies nicht immer der beste Weg ist, weil es einmal zu seltsamen Problemen geführt hat, die ich nicht beheben kann. Stattdessen ziehe ich es vor, HAProxy als Reverse-Proxy für Nginx und Apache zu verwenden . HAProxy ist ein kostenloser, hochverfügbarer Open-Source-Load-Balancer und Proxy-Server für TCP- und HTTP-basierte Anwendungen.
Apache, Nginx und HAProxy auf demselben Server ausführen
So funktioniert es.
- Nginx lauscht auf 127.0.0.1:80 und 127.0.0.1:443
- Apache überwacht 127.0.0.2:80 und 127.0.0.2:443
- HAProxy lauscht auf Port 80 und 443 der öffentlichen IP-Adresse. Es leitet die HTTP-Anfrage auf Port 80 an Port 443 um. Wenn eine Anfrage auf Port 443 eintrifft, wählt es zwischen Nginx- und Apache-Backend aus, indem es den SNI-Header (Server Name Indication) in der HTTPS-Anfrage analysiert.
Tatsächlich verwendet Cloudflare (ein CDN-Anbieter) auch den SNI-Header, um zu bestimmen, wie HTTPS-Anfragen an Ursprungsserver weitergeleitet werden.
Schritt 1:Stoppen Sie Nginx und Apache
Um Nginx unter Debian, Ubuntu und CentOS zu stoppen, führen Sie
aussudo systemctl stop nginx
Um Apache unter Debian/Ubuntu zu stoppen, führen Sie
aussudo systemctl stop apache2
Um Apache unter CentOS zu stoppen, führen Sie
aussudo systemctl stop httpd
Schritt 2:Ändern Sie den Listen-Port in Nginx
Wir müssen Nginx dazu bringen, auf 127.0.0.1:80 zu lauschen. Öffnen Sie Ihre Nginx-Konfigurationsdateien in /etc/nginx/conf.d/
oder /etc/nginx/sites-enabled/
und finden Sie die folgende Zeile.
listen 80;
Ändern Sie es in
listen 127.0.0.1:80;
Wenn https auf dem Nginx-Serverblock aktiviert ist, finden Sie auch
listen 443 ssl;
Und ändern Sie es in
listen 127.0.0.1:443 ssl;
Die Hauptkonfigurationsdatei von Nginx /etc/nginx/nginx.conf
kann einen standardmäßigen virtuellen Host enthalten, der auf Port 80 oder 443 lauscht, daher müssen Sie möglicherweise auch diese Datei bearbeiten.
Starten Sie Nginx neu, damit die Änderungen wirksam werden.
sudo systemctl restart nginx
Schritt 3:Ändern Sie den Listen-Port in Apache
Wir müssen Apache dazu bringen, auf 127.0.0.2:80 zu lauschen.
Debian/Ubuntu
Bearbeiten Sie unter Debian und Ubuntu die /etc/apache2/ports.conf
Datei.
sudo nano /etc/apache2/ports.conf
Ändern
Listen 80 Listen 443
An
Listen 127.0.0.2:80 Listen 127.0.0.2:443
Speichern und schließen Sie die Datei. Gehen Sie auch zu /etc/apache2/sites-enabled/
bearbeiten Sie die Dateien des virtuellen Hosts. Ändern
<VirtualHost *:80>
An
<VirtualHost 127.0.0.2:80>
Wenn es virtuelle SSL-Hosts gibt, ändern Sie auch
<VirtualHost *:443>
An
<VirtualHost 127.0.0.2:443>
Starten Sie Apache neu.
sudo systemctl restart apache2
CentOS
Bearbeiten Sie unter CentOS die Datei /etc/httpd/conf/httpd.conf
Datei.
sudo nano /etc/httpd/conf/httpd.conf
Suchen
Listen 80
Ändern Sie es in
Listen 127.0.0.2:80
Speichern und schließen Sie die Datei. Gehen Sie dann zu /etc/httpd/conf.d/
bearbeiten Sie die Dateien des virtuellen Hosts. Ändern
<VirtualHost *:80>
An
<VirtualHost 127.0.0.2:80>
Wenn es virtuelle SSL-Hosts gibt, ändern Sie auch
<VirtualHost *:443>
An
<VirtualHost 127.0.0.2:443>
In der /etc/httpd/conf.d/ssl.conf
Datei gibt es
Listen 443 https
Ändern Sie es in:
Listen 127.0.0.2:443 https
Speichern und schließen Sie die Datei. Starten Sie Apache neu, damit die Änderungen wirksam werden.
sudo systemctl restart httpd
Schritt 4:HAProxy konfigurieren
Installieren Sie HAProxy auf Ihrer Distribution.
Debian/Ubuntu
sudo apt install haproxy
CentOS
sudo dnf install haproxy
HAProxy-Konfigurationsdatei bearbeiten.
sudo nano /etc/haproxy/haproxy.cfg
Fügen Sie das folgende Code-Snippet am Ende der Datei hinzu, wodurch HAPorxy auf Port 80 der öffentlichen IP-Adresse lauschen und HTTP-Anfragen auf Port 80 auf Port 443 umleiten wird. Ersetzen Sie 12.34.56.78 durch die öffentliche IP-Adresse Ihres Servers.
frontend http bind 12.34.56.78:80 mode http redirect scheme https code 301
Jetzt müssen wir auch noch ein HTTPS-Frontend hinzufügen.
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 }
Definieren Sie dann die Nginx- und Apache-Backends. Der check
Der Parameter weist HAProxy an, Zustandsprüfungen am Backend durchzuführen, indem ein TCP-Paket gesendet wird.
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
Sie können ein Standard-Backend definieren mit:
default_backend nginx
Wir werden den SNI-Header in der HTTPS-Anforderung verwenden, um zum richtigen Backend umzuleiten. Zum Beispiel, wenn Nginx domain1.com
bedient und Apache bedient domain2.com
, dann fügen Sie die folgenden zwei Zeilen hinzu. Sie können auch Subdomains verwenden, solange sie unterschiedlich sind.
use_backend nginx if { req_ssl_sni -i domain1.com } use_backend apache if { req_ssl_sni -i domain2.com }
Beachten Sie, dass das default_backend
und use_backend
Direktiven sollten über den Backend-Definitionen platziert werden.
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
In der obigen Konfiguration haben wir die SNI-Funktion (Server Name Indication) in TLS verwendet, um den HTTPS-Datenverkehr zu unterscheiden.
- Wenn sich domain1.com im TLS-Client Hello befindet, leitet HAProxy den Datenverkehr an
nginx
um Backend. - Wenn sich domain2.com im TLS-Client Hello befindet, leitet HAProxy den Datenverkehr an den
apache
um Backend.
Wenn der Client den Servernamen nicht in TLS Client Hello angibt, verwendet HAproxy das Standard-Backend (nginx).
Speichern und schließen Sie die Datei. Starten Sie dann HAproxy neu.
sudo systemctl restart haproxy
Jetzt können Apache, Nginx und HAProxy auf demselben Server ausgeführt werden.
So leiten Sie die IP-Adresse des Clients an das Backend weiter
Standardmäßig können Apache und Nginx nur die IP-Adresse von HAProxy sehen. Stellen Sie sicher, dass Sie send-proxy-v2
hinzugefügt haben, um die echte IP-Adresse des Clients zu erhalten Option in der Backend-Definition von HAProxy wie unten.
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
Wir müssen auch einige Konfigurationen in Nginx und Apache hinzufügen, damit es funktioniert, sonst ist Ihre Website nicht zugänglich.
Nginx
Fügen Sie proxy_protocol
hinzu im Nginx listen
Direktive wie unten.
listen 127.0.0.2:443 ssl http2 proxy_protocol;
Fügen Sie dann die folgenden zwei Anweisungen in Nginx http { }
hinzu Block in /etc/nginx/nginx.conf
Datei.
set_real_ip_from 127.0.0.1; real_ip_header proxy_protocol;
Speichern und schließen Sie die Datei. Laden Sie dann Nginx neu.
sudo systemctl reload nginx
Hinweis :Wenn Ihre Website hinter Cloudflare CDN läuft, sollten Sie real_ip_header proxy_protocol;
ändern zu real_ip_header CF-Connecting-IP;
um die echte IP-Adresse des Clients anzuzeigen. Sie können auch diesen real_ip_header
hinzufügen Direktive an die einzelne Serverblockdatei, um die globale Konfiguration in /etc/nginx/nginx.conf
zu überschreiben Datei.
Starten Sie schließlich HAProxy neu.
sudo systemctl restart haproxy
Apache
Wenn Sie Apache unter Debian/Ubuntu verwenden, müssen Sie remoteip aktivieren Modul. (Dieses Modul ist unter CentOS standardmäßig aktiviert.)
sudo a2enmod remoteip
Fügen Sie dann die folgenden 3 Zeilen in Ihre Konfigurationsdatei für den virtuellen Apache-Host ein.
RemoteIPProxyProtocol On RemoteIPHeader X-Forwarded-For RemoteIPTrustedProxy 127.0.0.1
So.
<VirtualHost 127.0.0.2:443> ServerName www.example.com RemoteIPProxyProtocol On RemoteIPHeader X-Forwarded-For RemoteIPTrustedProxy 127.0.0.1
Speichern und schließen Sie die Datei. Dann müssen wir auch den combined
ändern Protokollformat. Bearbeiten Sie die Apache-Hauptkonfigurationsdatei.
sudo nano /etc/apache2/apache2.conf
oder
sudo nano /etc/httpd/conf/httpd.conf
Suchen Sie die folgende Zeile.
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
Ersetzen Sie es durch:
LogFormat "%a %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\"" combined
Speichern und schließen Sie die Datei. Starten Sie dann Apache neu, damit die Änderungen wirksam werden.
sudo systemctl restart apache2
oder
sudo systemctl restart httpd
Hinweis dass das RemoteIPProxyProtocol On
Direktive ist nur in Apache 2.4.31 und höher verfügbar. Um Ihre Apache-Version zu überprüfen, führen Sie
sudo apache2 -v
oder
sudo httpd -v
Ubuntu 18.04 wird mit Apache 2.4.29 ausgeliefert. Wenn Ihre Apache-Version diese Anforderung nicht erfüllt, sollten Sie send-proxy-v2
entfernen in der HAProxy-Backend-Definition. CentOS 8 wird mit Apache 2.4.37 ausgeliefert.
Starten Sie schließlich HAProxy neu.
sudo systemctl restart haproxy
So fügen Sie neue virtuelle Hosts hinzu
Wenn Sie Apache- und Nginx-Webserver haben, benötigen Sie nur zwei Backends:eines für Apache und eines für Nginx.
Wenn Sie eine weitere Domain (oder Subdomain) hinzufügen müssen, müssen Sie kein neues Backend in HAProxy hinzufügen. Stattdessen sollten Sie einen neuen virtuellen Host für die neue Domain (oder Subdomain) in Apache oder Nginx erstellen und dann das use_backend
verwenden Anweisung in HAProxy, um den Datenverkehr an das richtige Backend umzuleiten.
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
Ich empfehle die Verwendung von apache
und nginx
als Backend-Namen wie im obigen Code, damit Sie wissen, welcher Webserver welche Anwendung hostet.
Neues SSL-Zertifikat von Let’s Encrypt erhalten
http-01-Herausforderung
Zuerst müssen Sie verstehen, wie Sie den Certbot-Apache und den Nginx-Authentifikator verwenden, um ein TLS-Zertifikat zu erhalten.
- Aktivieren Sie HTTPS auf Apache ordnungsgemäß mit Let’s Encrypt auf Ubuntu
- Aktivieren Sie HTTPS auf Nginx ordnungsgemäß mit Let’s Encrypt auf Ubuntu
Der Certbot-Apache und der nginx-Authentifikator verwenden http-01
Challenge, die auf TCP-Port 80 funktioniert. Da HAProxy TCP-Port 80 verwendet, also der Certbot http-01
Herausforderung wird wahrscheinlich scheitern. Sie können es jedoch mit der folgenden Methode zum Laufen bringen.
- SSL-Host in Apache oder Nginx mit einem selbstsignierten Zertifikat oder einem Zertifikat für eine andere Domain aktivieren.
- Verwenden Sie dann den Certbot-Apache und den nginx-Authentifikator wie gewohnt.
Diese Methode funktioniert, weil der Certbot http-01
Challenge kann von TCP-Port 80 auf TCP-Port 443 umgeleitet werden, und Certbot akzeptiert ungültige Zertifikate auf Port 443.
dns-01-Herausforderung
Sie können auch den Certbot dns-01
verwenden Herausforderung, bei der ein temporärer TXT-Eintrag für Ihre Domain erstellt wird, um zu bestätigen, dass Sie diese Domain tatsächlich besitzen, sodass TCP-Port 80 und TCP-Port 443 umgangen werden können. Der Nachteil dieser Methode besteht darin, dass nicht alle Domain-Registrare unterstützt werden.
Zuerst müssen Sie das Certbot DNS-Plugin installieren. Es handelt sich um mehrere DNS-Plug-ins, die im Debian- und Ubuntu-Software-Repository verfügbar sind, das Sie mit
finden könnenapt search python3-certbot-dns
Ausgabe:
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
Unter CentOS 8 finden Sie Certbot-DNS-Plugins aus dem EPEL-Repository. Beachten Sie, dass Sie Certbot aus dem standardmäßigen CentOS-Repository installieren müssen.
sudo dnf install certbot
Finden Sie DNS-Plugins aus dem EPEL-Repository.
sudo dnf install epel-release dnf search certbot-dns
Ausgabe:
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
Installieren Sie eines dieser Plugins, je nachdem, welchen DNS-Hosting-Dienst Sie verwenden. Ich verwende Cloudflare, also werde ich Cloudflare als Beispiel verwenden. Führen Sie den folgenden Befehl aus, um python3-certbot-dns-cloudflare
zu installieren Paket auf Debian/Ubuntu.
sudo apt install python3-certbot-dns-cloudflare
Erstellen Sie dann eine Konfigurationsdatei für Cloudflare.
sudo nano /etc/letsencrypt/cloudflare.ini
Wir müssen die E-Mail-Adresse unseres Cloudflare-Kontos und den API-Schlüssel in diese Datei einfügen.
# Cloudflare API credentials used by Certbot dns_cloudflare_email = [email protected] dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567
Sie finden Ihren Cloudflare-API-Schlüssel unter https://dash.cloudflare.com/profile
. Beachten Sie, dass das Certbot Cloudflare-Plug-in derzeit die „API-Tokens“ von Cloudflare nicht unterstützt. Stellen Sie daher sicher, dass Sie den „Global API Key“ zur Authentifizierung verwenden.
Speichern und schließen Sie die Datei. Der API-Schlüssel umgeht die Zwei-Faktor-Authentifizierung von Cloudflare, daher sollten Sie nur dem Root-Benutzer erlauben, diese Datei zu lesen.
sudo chmod 600 /etc/letsencrypt/cloudflare.ini
Führen Sie jetzt certbot aus.
sudo certbot --agree-tos -a dns-cloudflare -i nginx --redirect --hsts --staple-ocsp --email [email protected] -d www.your-domain.com,your-domain.com
Im obigen Befehl haben wir angegeben, dass wir dns-cloudflare
verwenden werden als Authentifikator, um ein neues TLS-Zertifikat zu erhalten, und verwenden Sie den nginx
Plugin zum Erstellen des HTTPS-Serverblocks. Wenn Sie Apache verwenden, ersetzen Sie nginx
mit apache
.
Dieser Befehl fordert Sie auf, den Pfad der .ini
einzugeben Datei, geben Sie also /etc/letsencrypt/cloudflare.ini
ein und drücken Sie die Eingabetaste.
Nachdem das SSL-Zertifikat abgerufen und in der Konfigurationsdatei des Webservers installiert wurde. Sie müssen es auf 127.0.0.1:443 oder 127.0.0.2:443 hören lassen. Wenn Sie beispielsweise Nginx verwenden, suchen Sie
listen 443 ssl
Und ändern Sie es in
listen 127.0.0.1:443 ssl http2
Ändern Sie außerdem Port 80 in
listen 127.0.0.1:80;
Speichern und schließen Sie die Datei. Starten Sie dann Ihren Webserver neu.
Häufige Fehler
1 Falscher Domänenname
Wenn Sie mehrere virtuelle Nginx-Hosts auf einem Server haben und wenn Sie einen Domänennamen eingeben, führt Sie der Webbrowser zu einem anderen Domänennamen, der auf demselben Server gehostet wird, kann es sein, dass einer Ihrer virtuellen Nginx-Host-Dateinamen nicht endet mit der .conf
Dateinamenerweiterung, sodass Nginx diesen virtuellen Host nicht geladen hat. Es kann auch sein, dass Sie einen AAAA-Eintrag für den Domainnamen festgelegt haben, aber Sie haben Nginx nicht so konfiguriert, dass der Domainname in IPv6 bereitgestellt wird.
Das Obige gilt auch für den Apache-Webserver.
2 Verletzung des Netzwerkprotokolls
Wenn Sie den send-proxy-v2
Header in HAProxy, aber proxy_protocol
nicht aktiviert in Nginx oder Apache, dann zeigt Ihre Website den folgenden Fehler an.
The site has experienced a network protocol violation that cannot be repaired.
Denken Sie daran, Nginx/Apache neu zu starten, nachdem Sie Änderungen an der Konfigurationsdatei vorgenommen haben.
3 PR_CONNECT_RESET_ERROR
Wenn Sie proxy_protocol
aktivieren in Nginx oder Apache, aber send-proxy-v2
nicht gesetzt Header in HAProxy, dann zeigt Ihre Website diesen Fehler an.
secure connection failed. PR_CONNECT_RESET_ERROR
Und Sie finden die folgende Fehlermeldung im Nginx- oder Apache-Fehlerprotokoll.
broken header while reading PROXY protocol
Denken Sie daran, Nginx/Apache neu zu starten, nachdem Sie Änderungen an der Konfigurationsdatei vorgenommen haben.
Beachten Sie auch, dass, wenn Sie das proxy protocol
aktivieren in einer virtuellen Apache/Nginx-Hostdatei, dann ist es auch implizit für alle anderen virtuellen Hosts aktiviert. Und ich habe keine Möglichkeit gefunden, proxy_protocol
zu deaktivieren für einzelne virtuelle Hosts. Da Sie Apache und Nginx auf demselben Server ausführen, besteht eine Problemumgehung darin, dass Sie das Proxy-Protokoll nur in Nginx aktivieren und es nicht in Apache aktivieren. Wenn ein virtueller Host die echte IP-Adresse des Clients nicht abrufen muss, konfigurieren Sie ihn für die Verwendung von Apache.
Aktualisieren :Mir ist aufgefallen, dass Sie einen neuen virtuellen Apache/Nginx-Host auf einer anderen Loopback-Adresse wie 127.0.0.4 einrichten können. Auf diese Weise aktiviert der neue virtuelle Host kein Proxy-Protokoll.
4 PR_END_OF_FILE_ERROR
Wenn Sie das Proxy-Protokoll in Apache/Nginx aktiviert haben, aber versuchen, direkt auf den virtuellen Host zuzugreifen (unter Umgehung von HAProxy), wird der folgende Fehler angezeigt.
PR_END_OF_FILE_ERROR
5 SSL_ERROR_SYSCALL
Wenn Sie den Curl-Befehl verwenden:
curl -I https://example.com
Und Sie stoßen auf den folgenden Fehler
curl: (35) OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to example.com:443
Das liegt wahrscheinlich daran, dass Sie keine Backend-Definition für diese Domain festgelegt haben.