Warum ein Listen 443 default_server; Nginx-Regel überschreiben bereits konfigurierte Regel (http-Regeln funktionieren normal)?

9

Ich habe einen Nginx und verschiedene Subdomains:

a.mydomain.com
b.mydomain.com
c.mydomain.com

Nginx hat 4 Regeln:

1) Regel umschreiben:

server {
  listen 80
  server_name gl.udesk.org;

  root /nowhere;
  rewrite ^ https://a.mydomain.com$request_uri permanent;
}

2) https-Regel:

server {

  listen 443;
  server_name a.mydomain.com;

  root /home/a/a/public;

  ssl on;
  ssl_certificate conf.d/ssl/a.crt;
  ssl_certificate_key conf.d/ssl/a.key;
  ssl_protocols ...
  ssl_ciphers ...
  ssl_prefer_server_ciphers on;

  location ...
}

3) http-Standardregel:

server {
  listen 80 default_server;
  return 444;
}

4) https-Standardregel:

server {
  listen 443 default_server;
  return 444;
}

Also, wenn ich nginx starte und:

  • Wenn ich im Browser zu http://a.mydomain.com gehe, wird er zu https://a.mydomain.com umgeleitet und gibt dann einen Fehler 107 (net :: ERR_SSL_PROTOCOL_ERROR) zurück: SSL-Protokollfehler.
  • Wenn ich im Browser zu https://b.mydomain.com gehe, erwarte ich, dass der Fehler 444 zurückgegeben wird. Stattdessen wird derselbe Fehler 107 (net :: ERR_SSL_PROTOCOL_ERROR) zurückgegeben: SSL-Protokollfehler.
  • und so für alle vom DNS-Anbieter registrierten CNAMEs (dh a, b, c)
  • Alle http-Versionen (zB Regel 3 -) funktionieren wie erwartet:

Warum sind die https-Regeln in Nginx so schwierig zu konfigurieren und wie sollte ich sie richtig konfigurieren, um das gleiche Verhalten wie bei der http-Version zu erzielen?

Aktualisieren:

Erstellen eines neuen Zertifikats und Hinzufügen von:

ssl on;
ssl_certificate conf.d/ssl/default.crt;
ssl_certificate_key conf.d/ssl/default.key;

funktioniert jetzt, aber ich hätte eine Lösung ohne ein SSL-Zertifikat benötigt. Setzen Sie einfach alle Verbindungen für alle https-Subdomänen (Port 443) mit Ausnahme von https://a.mydomain.com zurück, ohne ein Zertifikat bereitzustellen.

statisch
quelle
2
Das kannst du nicht. SSL erfordert ein Zertifikat, bevor der Webserver weiß, welche Domain Sie möchten . Es muss ein Zertifikat zum Senden haben, oder es kann keine Verbindung herstellen, um mit dem Client zu kommunizieren.
Darth Android
2
@DarthAndroid: Die Magie heißt SNI - en.wikipedia.org/wiki/Server_Name_Indication .
Shi
@Shi Mir ist SNI bekannt. Dadurch kann der Webserver auswählen, welches Zertifikat gesendet werden soll , muss jedoch noch ein Zertifikat auswählen . nginxist nicht klug genug zu erkennen, dass es kein Zertifikat für das benötigt, was der Benutzer tun möchte.
Darth Android

Antworten:

3

Mischen Sie Port 443 nicht mit ssl! Nginx ist völlig portunabhängig. Sie können https auch über Port 80 anbieten. Moderne Nginx-Versionen erlauben

listen 1234 ssl;

und du brauchst die ssl on;Leitung dann nicht.

Wenn Sie jedoch https bereitstellen möchten, müssen Sie ein Zertifikat angeben. Ihr Server gibt https ein, wenn er die http-Anforderung in eine https-Anforderung umschreibt.

Sie erhalten den PROTOKOLLFEHLER, da der SSL-Handshake vor allem anderen ausgeführt wird. Also return 444nicht erreicht. Und jeder SSL-Handshake benötigt ein Zertifikat und einen privaten Schlüssel, um die Verschlüsselungsalgorithmen mit dem Zertifikat / privaten Schlüsselpaar zu versorgen.

ikrabbe
quelle
3

Die returnDirektive ist Teil des Rewrite-Moduls. Wenn Sie die Dokumentation überprüfen , sehen Sie möglicherweise, dass sie mit Anforderungen funktioniert. In HTTPS können Anforderungen erst nach Abschluss des Handshakes gestellt werden.

Es gibt eine Funktionsanforderung: https://trac.nginx.org/nginx/ticket/195, und es wird eine Problemumgehungslösung bereitgestellt.

server {
    listen 443 ssl;
    server_name bbb.example.com;
    ssl_ciphers aNULL;
    ssl_certificate /path/to/dummy.crt;
    ssl_certificate_key /path/to/dummy.key;
    return 444;
}
VBart
quelle
Beachten Sie, dass dadurch nicht SNI-fähige HTTPS-Clients (wie die von nginx proxy_pass, sofern Sie dies nicht festgelegt haben proxy_ssl_server_name on;) daran gehindert werden, andere zu erreichen server_names(brechen server_nameSie also im Wesentlichen die legitimen s, die Sie durchlassen möchten). Weitere Informationen finden Sie unter trac.nginx.org/nginx/ticket/195#comment:11 .
nh2