Nginx SSL Preread erhält sporadisch Anfragen, bei denen kein Servername extrahiert wird

Nginx SSL Preread erhält sporadisch Anfragen, bei denen kein Servername extrahiert wird

Ich verwende dieNginx-Stream-Modulum nginx als TCP-Reverse-Proxy vor S3 zu nutzen. Vor Kurzem musste ich Logik hinzufügen, um einen zusätzlichen Upstream unterzubringen. Dazu habe ich mich für die Verwendung einer bedingten Logik über die Map-Variable $ssl_preread_server_name entschieden.ssl_prereadermöglicht es nginx, den Servernamen aus der ClientHello-Nachricht zu extrahieren, ohne SSL zu beenden. Sie können die Logik unten sehen:

map $ssl_preread_server_name $https_cname {
    s3.amazonaws.com https_s3_backend;
    aws-service-2.amazonaws.com aws-service-2-backend;
}
upstream https_s3_backend {
    server s3.amazonaws.com:443;
}
upstream aws_service_2_backend {
    server aws-service-2.amazonaws.com:443;
}

server {
    listen       443;
    proxy_pass $https_cname;
    ssl_preread on;
}

Wenn eine Anfrage mit dem Servernamen s3.amazonaws.com eingeht, wird die Anfrage an s3 gesendet. Wenn eine Anfrage mit dem Servernamen aws-service-2.amazonaws.com eingeht, wird die Anfrage an aws-service-2 gesendet.

Meistens funktioniert das. Manchmal gibt es jedoch Fehler im Fehlerprotokoll, die darauf hinweisen, dass Anfragen ohne Servernamen an den Nginx-Servern auf Port 443 eingehen.

[error] ... no host in upstream "", client: x.x.x.x, server: 0.0.0.0:443

Wenn ich in der Map-Logik eine Standardanweisung einfüge, verschwinden diese Fehler. Was sind mögliche Erklärungen dafür, dass einige S3-Anfragen ohne extrahierten Servernamen eingehen? Anfragen können diese Nginx-Boxen derzeit nur erreichen, wenn jemand eine S3-Operation durchführt.

Antwort1

Ich bin mit Amazon S3 als solchem ​​nicht vertraut, aber ich denke, dass das Problem darin besteht, dass die Anfragen ohne Angabe des Servernamens generiert werden (sieheServernamenanzeige).

Ich hatte genau dasselbe Problem in einer ähnlichen Konfiguration und konnte es beispielsweise in OpenSSL v1.0.2p reproduzieren, indem ich eine Verbindung herstellte, ohne den Servernamen-Parameter explizit festzulegen:

openssl s_client -connect <mydomain>:<some_port> -showcerts

Diese Anfrage würde mir nur das Zertifikat des Standardservers liefern und den Domänennamen, den ich in der URL angegeben habe, nicht berücksichtigen. Andererseits gilt bei der Angabe des Servernamen-Parameters:

openssl s_client -connect <mydomain>:<some_port> -showcerts -servername <mydomain>

.. die Anfrage wird an die richtige Domäne gesendet und das richtige Zertifikat wird zurückgegeben.

Beim Zugriff auf denselben Webserver mit Curl oder über Webbrowser kann ich dieses Problem nicht beobachten. Ich vermute, dass die Implementierung im Webbrowser und in Curl den Servernamen festlegen, indem er im Hintergrund aus der URL extrahiert wird, während einige clientseitige Anwendungen wie OpenSSL ihn als optionalen Parameter behandeln.

Ich schätze, in Ihrem Fall müssen Sie Folgendes tun:

  • Finden Sie heraus, wo die Anfragen generiert werden
  • prüfen Sie, ob es eine Option zum Festlegen des Servernamens gibt

verwandte Informationen