Ermöglicht das Verschlüsseln mit einem Nginx-Reverse-Proxy

45

Einführung

Ich habe einen Entwickler-Server (derzeit mit Ubuntu 14.04 LTS), auf dem ich seit einiger Zeit verschiedene Entwicklungstools auf verschiedenen Ports hoste. Da die Ports schwer zu merken sein können, habe ich mich entschieden, Port 80 für alle meine Dienste zu verwenden und die Portweiterleitung intern basierend auf dem Hostnamen durchzuführen.

Anstatt domain.com:5432 zu schreiben, kann ich einfach über sub.domain.com darauf zugreifen

Beispielsweise hat die Anwendung X, die den Port 7547 verwendet und auf sub.domain.com ausgeführt wird, die folgende nginx-Konfiguration:

upstream sub {
    server 127.0.0.1:7547;
}

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    access_log /var/log/nginx/sub.log combined;
    location / {
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://127.0.0.1:7547;
            proxy_set_header Authorization "";
    }
}

Die Frage

Ist es bei der von mir gewählten aktuellen Konfigurationsstruktur möglich, letsencrypt zu verwenden und die verschiedenen Dienste unter https auszuführen?

0x450
quelle
3
Ich schrieb einen Blog-Beitrag zu diesem Thema: tom.busby.ninja/letsecnrypt-nginx-reverse-proxy-no-downtime
Tom Busby

Antworten:

81

Ja, Sie können Nginx-Proxy-Anforderungen an HTTP-Server senden und dann selbst über HTTPS auf Clients antworten. Wenn Sie dies tun, möchten Sie sichergehen, dass der nginx <-> Proxy-Connect wahrscheinlich nicht von jemandem beschnüffelt wird, von dem Sie einen Angriff erwarten. Zu den sicherheitsgerichteten Ansätzen könnten gehören:

  • Proxy zum selben Host (wie Sie)
  • Proxy für andere Hosts hinter Ihrer Firewall

Es ist unwahrscheinlich, dass das Proxying zu einem anderen Host im öffentlichen Internet sicher genug ist.

Hier finden Sie Anweisungen zum Beziehen eines Let's Encrypt-Zertifikats über denselben Webserver, den Sie als Proxy verwenden.

Fordern Sie Ihr erstes Zertifikat bei Let's Encrypt an

Ändern Sie Ihre serverKlausel, damit das Unterverzeichnis .well-knownvon einem lokalen Verzeichnis aus bedient werden kann, z.

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    […]
    location /.well-known {
            alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here
        […]
    }
}

http://sub.domain.com/.well-known Hier suchen die Let's Encrypt-Server nach Antworten auf die von ihnen gestellten Herausforderungen.

Sie können dann den certbot- Client verwenden, um ein Zertifikat von Let's Encrypt mithilfe des Webroot- Plugins (als Root) anzufordern :

certbot certonly --webroot -w /var/www/sub.domain.com/ -d sub.domain.com -d www.sub.domain.com

Ihr Schlüssel, Ihr Zertifikat und Ihre Zertifikatkette werden nun in installiert /etc/letsencrypt/live/sub.domain.com/

Nginx für die Verwendung Ihres Zertifikats konfigurieren

Erstellen Sie zunächst eine neue Server-Klausel wie folgt:

server {
    listen 443 ssl;

    # if you wish, you can use the below line for listen instead
    # which enables HTTP/2
    # requires nginx version >= 1.9.5
    # listen 443 ssl http2;

    server_name sub.domain.com www.sub.domain.com;

    ssl_certificate /etc/letsencrypt/live/sub.domain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/sub.domain.com/privkey.pem;

    # Turn on OCSP stapling as recommended at 
    # https://community.letsencrypt.org/t/integration-guide/13123 
    # requires nginx version >= 1.3.7
    ssl_stapling on;
    ssl_stapling_verify on;

    # Uncomment this line only after testing in browsers,
    # as it commits you to continuing to serve your site over HTTPS
    # in future
    # add_header Strict-Transport-Security "max-age=31536000";

    access_log /var/log/nginx/sub.log combined;

    # maintain the .well-known directory alias for renewals
    location /.well-known {
        alias /var/www/sub.domain.com/.well-known;
    }

    location / {
        # proxy commands go here as in your port 80 configuration
        […]
    }
}

Nginx neu laden:

service nginx reload

Stellen Sie sicher, dass HTTPS jetzt funktioniert, indem Sie https://sub.domain.comund https://www.sub.domain.comin Ihrem Browser (und allen anderen Browsern, die Sie speziell unterstützen möchten) aufrufen und überprüfen, dass sie keine Zertifikatfehler melden.

Empfohlen: Lesen Sie auch raymii.org: Starke SSL-Sicherheit auf nginx und testen Sie Ihre Konfiguration bei SSL Labs .

(Empfohlen) Leiten Sie HTTP-Anforderungen an HTTPS um

Wenn Sie bestätigt haben, dass Ihre Site mit der https://Version der URL funktioniert http://sub.domain.com, leiten Sie sie zur HTTPS-Version der Site weiter , anstatt dass einige Benutzer unsicheren Inhalt bereitstellen, weil sie dazu gegangen sind .

Ersetzen Sie Ihre gesamte Port 80- serverKlausel durch:

server {
    listen 80;
    server_name sub.domain.com www.sub.domain.com;
    rewrite     ^   https://$host$request_uri? permanent;
}

Sie sollten diese Zeile jetzt auch in der Konfiguration von Port 443 auskommentieren, damit die Browser nicht einmal die HTTP-Version der Site testen:

add_header Strict-Transport-Security "max-age=31536000";

Erneuern Sie Ihr Zertifikat automatisch

Sie können diesen Befehl (als root) verwenden, um alle Certbot bekannten Zertifikate zu erneuern und nginx mit dem neuen Zertifikat neu zu laden (das denselben Pfad wie Ihr vorhandenes Zertifikat hat):

certbot renew --renew-hook "service nginx reload"

certbot wird nur versuchen, Zertifikate zu erneuern, die älter als 60 Tage sind. Daher ist es sicher (und empfehlenswert!), diesen Befehl sehr regelmäßig und wenn möglich automatisch auszuführen . Sie könnten beispielsweise den folgenden Befehl eingeben /etc/crontab:

# at 4:47am/pm, renew all Let's Encrypt certificates over 60 days old
47 4,16   * * *   root   certbot renew --quiet --renew-hook "service nginx reload"

Sie können Erneuerungen entweder mit einem Testlauf testen, bei dem die Staging-Server von Let's Encrypt kontaktiert werden, um eine echte Prüfung der Kontaktaufnahme mit Ihrer Domain durchzuführen. Die resultierenden Zertifikate werden jedoch nicht gespeichert:

certbot --dry-run renew

Oder Sie können eine vorzeitige Verlängerung erzwingen mit:

certbot renew --force-renew --renew-hook "service nginx reload"

Hinweis: Sie können so oft trocken laufen, wie Sie möchten. Für echte Erneuerungen gelten jedoch die Grenzwerte für die Verschlüsselungsrate .

Verwirrung
quelle
Ihre Lösung scheint für mich nicht zu funktionieren. Ich habe im Grunde die gleiche Konfiguration. Es funktioniert für goopen.tk, aber nicht für www.goopen.tk
Alko
3
@Alko, die Anweisungen der Antwort sind korrekt und decken dieses Problem ab. Wenn Sie certbotein anderes Tool verwenden, dürfen Sie nicht vergessen, Ihre Domain sowohl im WWW- als auch im Nicht-WWW-Format anzugeben, damit sie funktioniert.
Paulo Coghi
Darunter location /.well-knownmusst du .well-knownim Weg auslassen. Verwenden Sie alias /var/www/sub.domain.com, nichtalias /var/www/sub.domain.com/.well-known
Gldraphael
1
Kann mir jemand erklären, warum Sie "rewrite ^ https: // $ host $ request_uri? Permanent;" verwenden möchten? hier anstelle von "return 301 https: // $ server_name $ request_uri;"
ZaxLofful
Ich stellte fest, dass ich Anführungszeichen für den Pfad vor Ort benötigte. location '/.well-known' {. Ich bin mir nicht sicher, ob es sich um eine Versionssache oder nur um mein Setup handelt, aber für den Fall, dass jemand anderes feststeckt.
Frank V
2

Ja, Sie können nginxhttps als Endpunkt verwenden und über http mit Backends zusammenarbeiten. Zum Beispiel meine Konfiguration:

server {
        server_name host;
        listen 443 ssl;
...
 location /svn/ {
            auth_ldap off;

            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;

            proxy_pass http://localhost:1080/svn/;
            proxy_redirect http://localhost:1080/ https://host/;
        }
...
}

Aber wie ich weiß, müssen Sie mit "Verschlüsseln" alle Unterdomänen angeben, wenn Sie ein Zertifikat erhalten. Wenn dies ein Problem ist, wählen Sie "URL" https://host/serviceanstelle von " URL"https://service.host

fghj
quelle