Wie richte ich mit nginx mehrere Subdomains mit einem eigenen Zertifikat ein?

8

Sofern nicht jede Antwort, die ich gelesen habe, einfach falsch war, sollte SNI es ermöglichen, das zu tun, was ich will, aber jeder Leitfaden fordert mich auf, genau das zu tun, was ich tue.

Und dennoch stellt Nginx das falsche Zertifikat bereit, sodass ich eindeutig etwas falsch mache.

❯ sudo nginx -V | grep SNI                                                                                                                                                                                                                                                            %1
nginx version: nginx/1.10.3
built with OpenSSL 1.1.0f  25 May 2017
TLS SNI support enabled
configure arguments: --with-cc-opt='-g -O2 -fdebug-prefix-map=/build/nginx-qJwWoo/nginx-1.10.3=. -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2' --with-ld-opt='-Wl,-z,relro -Wl,-z,now' --prefix=/usr/share/nginx --conf-path=/etc/nginx/ngi
nx.conf --http-log-path=/var/log/nginx/access.log --error-log-path=/var/log/nginx/error.log --lock-path=/var/lock/nginx.lock --pid-path=/run/nginx.pid --modules-path=/usr/lib/nginx/modules --http-client-body-temp-path=/var/lib/nginx/body --http-fastcgi-temp-path=/var/lib/nginx/fa
stcgi --http-proxy-temp-path=/var/lib/nginx/proxy --http-scgi-temp-path=/var/lib/nginx/scgi --http-uwsgi-temp-path=/var/lib/nginx/uwsgi --with-debug --with-pcre-jit --with-ipv6 --with-http_ssl_module --with-http_stub_status_module --with-http_realip_module --with-http_auth_reques
t_module --with-http_v2_module --with-http_dav_module --with-http_slice_module --with-threads --with-http_addition_module --with-http_geoip_module=dynamic --with-http_gunzip_module --with-http_gzip_static_module --with-http_image_filter_module=dynamic --with-http_sub_module --wit
h-http_xslt_module=dynamic --with-stream=dynamic --with-stream_ssl_module --with-mail=dynamic --with-mail_ssl_module --add-dynamic-module=/build/nginx-qJwWoo/nginx-1.10.3/debian/modules/nginx-auth-pam --add-dynamic-module=/build/nginx-qJwWoo/nginx-1.10.3/debian/modules/nginx-dav-
ext-module --add-dynamic-module=/build/nginx-qJwWoo/nginx-1.10.3/debian/modules/nginx-echo --add-dynamic-module=/build/nginx-qJwWoo/nginx-1.10.3/debian/modules/nginx-upstream-fair --add-dynamic-module=/build/nginx-qJwWoo/nginx-1.10.3/debian/modules/ngx_http_substitutions_filter_m
odule

So sehen meine Konfigurationen aus:

server {
  listen 443 ssl default_server;
  listen [::]:443 ssl;

  server_name one.example.com;

  ssl on;
  ssl_certificate       /etc/letsencrypt/live/one.example.com/fullchain.pem;
  ssl_certificate_key   /etc/letsencrypt/live/one.example.com/privkey.pem;

  index index.html;
  root /var/www/one.example.com/site;
}

server {
  #listen 443 ssl default_server;
  listen [::]:443 ssl;

  server_name two.example.com;

  ssl on;
  ssl_certificate       /etc/letsencrypt/live/two.example.com/fullchain.pem;
  ssl_certificate_key   /etc/letsencrypt/live/two.example.com/privkey.pem;

  index index.html;
  root /var/www/two.example.com/site;
}

Wenn ich die listen 443 ssl default_server;Anweisung auf einem der Server habe, wird das SSL-Zertifikat für diesen Server für BEIDE Domänen zurückgegeben. Wenn ich es von beiden Domänen entferne, bekomme ich überhaupt nichts - beide Serverdomänen lehnen Verbindungen ab.

Was habe ich hier falsch gemacht? Verstehe ich einfach nicht, wie SNI funktioniert? Mein Nginx wurde mit aktivierter SNI-Unterstützung erstellt. Und doch ... bekomme ich nur das SSL-Zertifikat für eine Subdomain.

Wayne Werner
quelle
Wie testest du? Wenn Sie mit testen, openssl s_clientstellen Sie sicher, dass Sie die -servername hostnameOption hinzufügen, damit der Client tatsächlich SNI verwendet.
Steffen Ullrich
@SteffenUllrich Chrome ist eine Möglichkeit, wie ich es gemacht habe. openssl s_client -servername two.example.com -connect two.example.com:443Ich habe es gerade versucht und es gibt mir die CN für one.example.com. Wenn ich tausche, welcher den Standardserver hat, bekomme ich die Dinge umgekehrt.
Wayne Werner
Und für Tritte und Grinsen habe ich es einfach verwechselt: -servername one -connect twound dann umgekehrt. Sowohl openssl s_client als auch chrome beobachten dasselbe Verhalten - das einzige offensichtliche definierende Merkmal ist die Standardserverzeile.
Wayne Werner
@SteffenUllrich scheint es, dass die IPv6-Syntax zum Hören etwas anderes macht? Ich habe eine Antwort gepostet, aber wenn das etwas für Sie auslöst, würde ich gerne mehr darüber erfahren, warum
Wayne Werner
Wenn ich mehrere Sites auf einem einzelnen Server habe, bevorzuge ich einen vollständig separaten default_serverBlock, der keine der beiden Sites zurückgibt.
Tero Kilkanen

Antworten:

11
listen 443 ssl default_server;
listen [::]:443 ssl;

Die erste Zeile ermöglicht das Abhören von Port 443 auf IPv4. Die zweite Zeile behandelt nur IPv6. Da Sie nur eine einzige listen 443(IPv4) Konfiguration haben, wird diese verwendet, wenn Sie eine Verbindung mit IPv4 herstellen. Wenn Sie stattdessen versuchen würden, eine Verbindung mit IPv6 herzustellen, sollte SNI das erwartete Verhalten anzeigen.

Stattdessen könnten Sie wahrscheinlich für den Standardserver verwenden:

  listen 443 ssl default_server;
  listen [::]:443 ssl default_server;

Und für den anderen Server

  listen 443 ssl;
  listen [::]:443 ssl;
Steffen Ullrich
quelle
2

Es hat anscheinend etwas mit der IPv6-Listen-Syntax zu tun. Wenn ich mich ändere

listen [::]:443 ssl;

zu

listen 443 ssl;

Dann funktioniert es.

Ich weiß nicht warum das so ist und würde andere Antworten mit mehr / besseren Erklärungen begrüßen.

Wayne Werner
quelle
Haben Sie sich also mit IPv4 oder IPv6 mit dem Server verbunden? Wenn Sie eine Verbindung zu IPv4 hergestellt haben, ist dies klar, da Sie nur eine IPv4-Konfiguration hatten - den Standardserver. Damit die IPv6-Konfiguration auch IPv4 abdeckt, müssen Sie hinzufügenipv6only=off;
Steffen Ullrich