Mam serwer WWW z wieloma serwerami wirtualnymi. Tylko 1 z nich to SSL. Problem polega na tym, że ponieważ nie istnieje blokujący serwer serwer nasłuchujący protokołu SSL, każde żądanie https do innych witryn jest obsługiwane przez 1 blok SSL.
Moja konfiguracja wygląda następująco:
# the catch all
server {
listen 80 default;
# I could add this, but since I have no default cert, I cannot enable SSL,
# and this listen ends up doing nothing (apparently).
# listen 443;
server_name _;
# ...
}
# some server
server {
listen 80;
server_name server1.com;
# ...
}
# some other server ...
server {
listen 80;
server_name server2.com;
# ...
}
# ... and it's https equivalent
server {
listen 443;
ssl on;
server_name server2.com;
# ...
}
Ponieważ teraz nie ma domyślnego nasłuchiwania dla 443, takie żądanie https://server1.com
zostanie obsłużone przez server2.com
blok https. Wynika to z logiki server_name
w docs.
Jeśli nie ma dopasowania, zostanie użyty blok serwera {...} w pliku konfiguracyjnym w następującej kolejności:
- blok serwera z pasującą dyrektywą nasłuchującą oznaczoną jako [default | default_server]
- pierwszy blok serwera z pasującą dyrektywą Listen (lub niejawnie Listen 80;)
Jakie jest preferowane rozwiązanie tego problemu? Czy muszę skonfigurować atrapę certyfikatu do przechwytywania wszystkich bloków serwera, aby móc słuchać na 443 i obsługiwać złe żądania? Czy jest parametr, którego nie znam, a który wymusza dokładne dopasowanie nazwy hosta server
?
Odpowiedzi:
Nie jest to możliwe. Połączenie od klienta, które przechodzi do https://foo.example.com/, nie może być zaakceptowane przez nic poza certyfikatem SSL z „foo.example.com” jako jedną z jego nazw. Nie ma możliwości przekierowania, dopóki połączenie SSL nie zostanie zaakceptowane.
Jeśli skonfigurujesz każdą witrynę dla protokołu SSL, użytkownik, który kliknie błąd certyfikatu, otrzyma żądaną witrynę. Jeśli skonfigurujesz witrynę „catch all” dla protokołu SSL, która zawiera tylko stronę błędu, i skonfigurujesz wirtualny hosting oparty na nazwie dla jednej witryny, która ma obsługiwać protokół SSL, możesz wyświetlić stronę błędu klientom.
Wirtualny hosting SSL i HTTP po prostu nie działają dobrze razem.
źródło
Jedynym sposobem jest utworzenie samopodpisanego certyfikatu SSL i wykorzystanie go do uzyskania kontroli nad przychodzącymi żądaniami https. Możesz utworzyć samopodpisany certyfikat SSL w kilku prostych krokach opisanych w tym poście .
Załóżmy, że tworzysz samopodpisany certyfikat z nazwą pliku server.crt. Następnie dołączysz do swojej konfiguracji nginx:
Nadal będziesz otrzymywać ostrzeżenie SSL dotyczące przeglądarki, ale przynajmniej będziesz mieć kontrolę nad tym, co będzie dalej.
źródło
Dodaj blok serwera typu catch-all i zwróć kod stanu 444. Mówi on nginx, aby zamknął połączenie przed wysłaniem jakichkolwiek danych.
źródło
Obecnie można korzystać z rozszerzenia TLS Server Name Indication (SNI, RFC 6066). Odbiornik HTTPS będzie mógł rozpoznać nazwę domeny przed podaniem odpowiedniego certyfikatu.
Oznacza to, że musisz mieć certyfikaty dla WSZYSTKICH domen, a gdy SNI jest używany do rozpoznania jednej z pozostałych domen, możesz po prostu użyć przekierowania HTTP 301 do niezaszyfrowanej wersji HTTP, chyba że nazwa serwera odpowiada tej, która potrzebuje szyfrowanie.
Więcej informacji o SNI dostępnych w dokumentacji nginx http://nginx.org/en/docs/http/configuring_https_servers.html
źródło
Odwzoruj żądaną nazwę hosta na prawidłowe nazwy hostów w
http {}
bloku:A następnie w
server {}
bloku zabij połączenia z niewłaściwą nazwą hosta:W razie potrzeby używaj wielu map dla wielu bloków serwerów. Połączenie nadal będzie nawiązywane przy użyciu jednego z twoich certyfikatów, ale jeśli ten ostatni blok jest obecny w każdym bloku serwera obsługującym SSL, wówczas skutecznie „zablokujesz” połączenia z nieprawidłowymi nazwami hostów. Może to być konieczne tylko w pierwszym bloku serwera, ale dodanie go do każdego bloku serwera zapewni, że kolejność nie będzie miała znaczenia.
$ssl_server_name
Zmienna występuje w nginx 1,7 lub więcej.źródło
Oto jak rozwiązałem problem:
openssl req -nodes -x509 -newkey rsa:4096 -keyout self_key.pem -out self_cert.pem -days 3650
cp self*.pem /etc/nginx/ssl/
Co to zrobi: wyświetli ostrzeżenie (nie można tego obejść) na dowolnym serwerze, który nie ma własnego certyfikatu, ale ostrzeżenie nie powie niewłaściwej nazwy certyfikatu. Jeśli użytkownik kliknie „mimo to odwiedź”, zostanie przekierowany do wersji strony, którą napisał.
zastrzeżenie :
jeśli twoja witryna obsługująca SLL definiuje
www.example.com
(a nie tylkoexample.com
), wtedy twoja trasa catch-all skończy sięhttps://example.com
z certyfikatem z podpisem własnym i odpowiednim ostrzeżeniem.źródło
Przekieruj na http:
Zwróć 404 :
źródło