Wie werden mehrere SSL-Zertifikate für den virtuellen Standardhost auf NGINX bereitgestellt?

Wie werden mehrere SSL-Zertifikate für den virtuellen Standardhost auf NGINX bereitgestellt?

Ich habe eine statische App auf Amazon S3, die über einen NGINX-Proxy bereitgestellt wird. Ich verwende einen Proxy, um Benutzern zu ermöglichen, ihre Domänen auf meine Amazon EC2-Instanz zu verweisen (über einen CNAME-Eintrag, der auf verweist custom-domain.myproduct.com), damit sie über ihre eigene benutzerdefinierte URL wie diese auf meine App zugreifen können: myproduct.happyclient.com.

Um dies zu erreichen, habe ich die folgende Nginx-Konfiguration (Teile der Kürze halber entfernt):

http {
    server {
    # This is my default route. References:
    # http://stackoverflow.com/a/15799883/91403
    # http://nginx.org/en/docs/http/request_processing.html

    listen 80 default_server;
    server_name custom-domain.myproduct.com;
    location / {
        proxy_pass http://static.myproduct.com; # points to Amazon S3
        proxy_set_header Host myproduct.com;
    }
}

Obwohl meine statische App zu 100 % öffentlich ist (kein Client-Geheimnis, nur HTML und JavaScript), möchten einige meiner Clients über SSL darauf zugreifen. Wie kann ich basierend auf dem Host-Header dynamisch auswählen, welches Zertifikat für die SSL-Verbindung verwendet werden soll? Beachten Sie, dass ich den Zertifikatspfad nicht einfach fest codieren kann.

PS.: Kunden können ihre Zertifikate in meine Instanz hochladen
PS2.: Dieses Setup funktioniert bereits einwandfrei nur mit HTTP.

Was ich versucht habe

Ich habe so etwas versucht, ohne Erfolg:

server {
    listen 443 default_server;
    server_name custom-domain.myproduct.com;
    ssl on;
    ssl_certificate /etc/nginx/ssl/$http_host/server.crt; # note the http_host variable
    ssl_certificate_key /etc/nginx/ssl/$http_host/server.key; # also here
}

Antwort1

Wie kann ich basierend auf dem Host-Header dynamisch auswählen, welches Zertifikat für die SSL-Verbindung verwendet werden soll?

Der Host-Header ist Teil des HTTP-Protokolls, aber HTTPS ist in eine SSL-Verbindung eingebettetes HTTP. Das bedeutet, dass Sie zuerst die SSL-Verbindung herstellen müssen (wofür das Zertifikat erforderlich ist), bevor Sie auf den Host-Header zugreifen können.

Wenn der Client SNI unterstützt (alle modernen Browser tun das, aber IE/XP nicht), sendet er den Zielnamen bereits im SSL-Handshake. Die Bereitstellung unterschiedlicher Zertifikate basierend auf dem Zielnamen erfolgt in nginx normalerweise über unterschiedliche Serverabschnitte. Sie könnten versuchen, dies $ssl_server_nameim Standardabschnitt zu verwenden, aber ich bin nicht sicher, ob das funktioniert, und selbst wenn es funktioniert, könnte es Optimierungen wie das Session-Caching negativ beeinflussen.

verwandte Informationen