Nginx. Jak odrzucić żądanie do serwera wirtualnego ssl niepublicznego?

14

Mam wieloznaczny certyfikat SSL i kilka subdomen na tym samym adresie IP. Teraz chcę, aby mój nginx obsługiwał tylko wspomniane nazwy serwerów i przerywał połączenia dla innych, aby wyglądało na to, że nginxnie działa dla nazw serwerów niepublicznych (nie odpowiada, odrzuca, nie działa, ani jednego bajtu w odpowiedzi). Robię następujące

ssl_certificate         tls/domain.crt;
ssl_certificate_key     tls/domain.key;

server {
  listen 1.2.3.4:443 ssl;
  server_name validname.domain.com;
  //
}

server {
  listen 1.2.3.4:443 ssl;
  server_name _;
  // deny all;
  // return 444;
  // return 404;
  //location {
  //  deny all;
  //}
}

Próbowałem prawie wszystkiego w ostatnim bloku serwera, ale bez powodzenia. Otrzymuję poprawną odpowiedź od znanego wirtualnego serwera lub kod błędu. Proszę pomóż.

andbi
źródło

Odpowiedzi:

7

To nie działa w ten sposób: uzgadnianie SSL odbywa się przed HTTP, więc nazwa na certyfikacie zostanie sprawdzona w przeglądarce, zanim będzie można przekierować lub zrobić cokolwiek innego w konfiguracji nginx.

cjc
źródło
to źle, ale muszę przyznać) Dzięki.
andbi
3
To nie jest prawda: możesz zrobić coś innego na niższym poziomie, na przykład porzucić połączenie bez żadnej odpowiedzi, jak wyjaśniono w innych odpowiedziach.
collimarco
14

Odpowiedź cjc już poprawnie wskazywała na problem z próbą dopasowania nazw hostów, gdy włączony jest SSL. Można to jednak zrobić w następujący sposób:

server {
    ...

    if ($host !~* ^validname\.domain\.com$ ) {
        return 444;
    }
    ...
}

Uwaga: tak, to prawda, że ​​ogólnie ifjest zły , ale ifw tym przypadku można go bezpiecznie używać . (Przeczytaj przekierowaną stronę, jeśli chcesz się przekonać).

W przeciwieństwie do tego, co zostało zasugerowane, dodanie następującego bloku nie zadziała:

server {
    listen 80;
    listen 443 ssl;
    return 444;
}

ponieważ validname.domain.compasujący certyfikat SSL nie pasuje do losowej nazwy domeny. Próbowałem i nginx zachowywał się, jakby blok w ogóle nie był obecny.

To również nie zadziała:

server {
    listen       443;
    server_name    _;
    return 444; 
}

ponieważ spowoduje to niepowodzenie każdego połączenia HTTPS na porcie 443, nawet tych, które powinny przejść. Też tego próbowałem. wgetzgłosił błąd uzgadniania protokołu SSL.

Louis
źródło
Ta odpowiedź jest absolutnie słuszna. Tylko dla tych, którzy wątpią, powinieneś dodać tę sekcję do działającej konfiguracji serwera. Tak więc dla tego tematu konfiguracja startowa to serwer {nasłuchuj 443 ssl; nazwa_serwera poprawna nazwa.domena.com; if ($ host! ~ * ^ ważna nazwa \ .domena \ .com $) {return 444; }}
Ivan Yaremchuk
6

Większość odpowiedzi tutaj dotyczy tego , dlaczego to nie działa, a nie, jak to zrobić.

Oto jak - musisz ustawić taki serwer typu catch-all na „default_server” i podać ścieżki do certyfikatu / klucza, aby mógł on odszyfrować przychodzące żądanie ssl i dopasować nagłówek hosta:

server {
    listen 80 default_server;
    listen 443 ssl default_server;
    server_name _;
    ssl_certificate <path to cert>;
    ssl_certificate_key <path to key>;
    return 404;
}

Zwróć uwagę na klucz ssl_certificate / ssl_certificate_key. Jeśli nie zostaną określone, nginx nadal próbuje użyć takiego serwera domyślnego i kończy się niepowodzeniem, ponieważ nie może zaakceptować połączenia ssl bez certyfikatu / klucza. Można użyć dowolnego certyfikatu / klucza, np. Z podpisem własnym. ...

Aby wygenerować samopodpisany certyfikat:

openssl req -x509 -newkey rsa:4096 -nodes -out cert.pem -keyout key.pem -days 365 

Zobacz także /server//a/841643/87439

andreycpp
źródło
1
Próbowałeś tego? Jak utworzyć certyfikat SSL zgodny z nazwą serwera „_”?
Tim
Tak, to rozwiązanie działa dla mnie. Miałem dokładnie ten sam problem i na podstawie dokumentacji zorientowałem się, że nginx potrzebuje certyfikatu / klucza, ponieważ nie patrzy na TLS SNI. Możesz użyć dowolnego certyfikatu / klucza, np. Z podpisem własnym.
andreycpp
1

Wdrożyłem powyższe rozwiązanie dzisiaj i działało płynnie. Wszystkie nieokreślone adresy URL są teraz usuwane. Umieszczenie tego kodu serwera przed faktycznym wpisem na serwerze wirtualnym było kluczowe - wszystkie źle sformułowane adresy URL trafiają teraz do tego „domyślnego” serwera.

... 
server {
     listen       443;
     server_name    _;
     return 444; }

server {
     listen       443;
     server_name  [URL]
David Sexton
źródło
0

Powinieneś być w stanie sobie z tym poradzić, ustawiając serwer, który obsługuje elementy niepubliczne, na pierwszy blok serwera w konfiguracji.

http {
    ...

    server {
        listen 80;
        listen 443 ssl;
        return 444;
    }

    server {
        server_name validname.domain.com;
        ...
    }
}

Wszystkie domeny nieokreślone konkretnie będą obsługiwane przez ten blok serwera.

Dayo
źródło
1
To nie działa
AmirHossein