Vraag Op de juiste manier een "standaard" nginx-server instellen voor https


Ik heb verschillende servers op dezelfde computer, sommige alleen met http, sommige met http en https. Er zijn verschillende serverblokken gedefinieerd in afzonderlijke bestanden die zijn opgenomen in het hoofdconfiguratiebestand.

Ik heb een "standaard" -server ingesteld voor http, die een generieke "onderhoudspagina" zal dienen voor verzoeken die niet overeenkomen met een van de andere server-namen in de andere configuratiebestanden. De http-standaardserver werkt zoals verwacht, deze gebruikt de servernaam "_" en deze verschijnt eerst in de lijst met include's (omdat ik heb vastgesteld dat in het geval van dubbele serversamen over servers, degene die als eerste verschijnt, wordt gebruikt). Dit werkt geweldig.

Ik zou hetzelfde exacte serverblok verwachten (alleen "luister 80 default_server" overschakelen naar "luister 443 default_server" en ook in plaats van pagina "return 444"), maar dat doet het niet. In plaats daarvan lijkt het erop dat de nieuwe standaard https-server daadwerkelijk alle inkomende https-verbindingen onderschept en ertoe leidt dat ze falen, hoewel de andere serverblokken meer geschikte server-namen hebben voor de binnenkomende verzoeken. Als u de nieuwe standaard https-server verwijdert, wordt het semi-correcte gedrag hervat: de websites met https worden allemaal correct geladen; maar de websites zonder https worden allemaal naar de eerste https-server in de include-bestanden gerouteerd (wat volgens de documenten, als er geen "default_server" verschijnt, het eerste serverblok dat verschijnt, "standaard" is).

Dus mijn vraag is, wat is de juiste manier om een ​​"standaardserver" te definiëren in nginx voor ssl-verbindingen? Hoe komt het dat wanneer ik expliciet een "default_server" instel, het hebberig wordt en alle verbindingen grijpt, terwijl wanneer ik impliciet laat zien dat nginx de "standaardserver" kiest, het werkt zoals ik zou verwachten (met de verkeerde server als standaard ingesteld en de andere echte servers zich correct gedragen)?

Dit zijn mijn "standaardservers". HTTP werkt zonder andere servers te onderbreken. Https breekt andere servers en verbruikt alles.

server {
    listen 443 ssl default_server;
    server_name _;

    access_log /var/log/nginx/maintenance.access.log;
    error_log /var/log/nginx/maintenance.error.log error;

    return 444;
}

server {
    listen *:80 default_server;
    server_name _;
    charset utf-8;

    access_log /var/log/nginx/maintenance.access.log;
    error_log /var/log/nginx/maintenance.error.log error;

    root /home/path/to/templates;

    location / {
        return 503;
    }

    error_page 503 @maintenance;

    location @maintenance {
        rewrite ^(.*)$ /maintenance.html break;
    }
}

Zien jullie hier wat er fout zou kunnen zijn?


56
2018-02-26 22:29


oorsprong




antwoorden:


U hebt geen ssl_certificate of ssl_certificate_key gedefinieerd in uw "standaard" https-blok. Hoewel u geen echte sleutel voor dit standaardscenario hebt of wilt, moet u er nog steeds een configureren of anders heeft nginx het ongewenste gedrag dat u beschrijft.

Maak een zelfondertekend certificaat met een algemene naam van * en sluit het aan op uw configuratie en het zal werken zoals u wilt.

Het "standaard" gedrag onder deze opstelling zou zijn dat een browser een waarschuwing krijgt dat het certificaat niet vertrouwd kan worden, als de gebruiker het certificaat als een uitzondering toevoegt, wordt de verbinding verbroken door nginx en zullen ze de standaardinstelling van hun browser zien "kon geen verbinding maken" foutmelding.


19
2018-02-27 16:27



Ik heb dit geprobeerd maar het werkt nog steeds niet: alle SSL-verzoeken naar het IP gaan naar mijn andere SSL-host. Kan ik nog iets anders proberen? - Michael Härtl


We willen ten koste van alles vermijden dat de eerste serverdefinitie in ons configuratiebestand wordt gebruikt als een catch-all-server voor SSL-verbindingen. We weten allemaal dat het dat doet (in tegenstelling tot http en het gebruiken van default_server-configuratie die goed werkt).

Dit kan voor SSL (nog) niet declaratief worden bereikt, dus we moeten het coderen met een IF ...

De variabele $host is de hostnaam van de aanvraagregel of de http-header. De variabele $server_name is de naam van het serverblok waarin we ons nu bevinden.

Dus als deze twee niet gelijk zijn, diende u dit SSL-serverblok voor een andere host, zodat dit moet worden geblokkeerd.

De code bevat geen specifieke verwijzingen naar de IP-adressen van uw server, zodat deze zonder wijzigingen eenvoudig kan worden hergebruikt voor andere serverconfigs.

Voorbeeld:

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

    ###
    ### Section: SSL

    #
    ## Check if this certificate is really served for this server_name
    ##   http://serverfault.com/questions/578648/properly-setting-up-a-default-nginx-server-for-https
    if ($host != $server_name) {
        #return 404 "this is an invalid request";
        return       444;
    }

    ...

13
2017-07-02 00:12



zou je kunnen uitleggen wat de listen [::]:443 ssl http2; doet? ik heb problemen met het vinden van documentatie hiervoor. - Andrew Brown
Ik denk dat ik het heb gevonden, ik moest gewoon weten waar ik naar moest zoeken. IPV4- en IPV6-richtlijnen. - Andrew Brown


Ik slaagde erin om een ​​shared dedicated hosting te configureren op een enkel IP met nginx. Standaard HTTP en HTTPS serveren een 404 voor onbekende inkomende domeinen.

1 - Maak een standaardzone

Omdat nginx vhosts in ascii-volgorde laadt, moet u een 00-default bestand / symbolische link naar uw /etc/nginx/sites-enabled.

2 - Vul de standaardzone in

Vul uw 00-default met standaardvhosts. Dit is de zone die ik gebruik:

server {
    server_name _;
    listen       80  default_server;
    return       404;
}


server {
    listen 443 ssl;
    server_name _;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    return       404;
}

3 - Maak een zelfondertekende certificering, test en herlaad

U moet een zelf ondertekend certificaat maken in /etc/nginx/ssl/nginx.crt.

Maak een standaard zelf ondertekend certificaat:

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.crt

Gewoon een herinnering:

  • Test de nginx-configuratie voordat u herlaadt / herstart: nginx -t
  • Herlaad een geniet van: sudo service nginx reload

Hoop dat het helpt.


12
2018-04-24 11:52



Lost de browser waarschuwing voor het bezoeken van een onveilige site niet op. - gdbj
Kan niet worden opgelost omdat een verzamelnaam moet overeenkomen met domeinen. Geen SSL kan alle domeinen van een wildcard voorzien. Stel je voor dat je je google.fr-adres vervalst op je server, dan kun je je server authenticeren als google.fr. Het zou een serieus beveiligingsprobleem zijn :( - Ifnot
Ja, ik denk dat dat logisch is. Helaas wordt u in Chrome een enge waarschuwing aangeboden voordat u de 404-pagina ziet die erger is dan dat de server het verkeer eenvoudigweg afwijst. Hierdoor lijkt het of de server verkeerd is geconfigureerd. - gdbj


Om meer uit te leggen over het antwoord van Radmilla Mustafa:

Nginx gebruikt de header 'Host' voor het matchen van de servernaam. Er wordt geen TLS SNI gebruikt. Dit betekent dat voor een SSL-server, nginx SSL-verbinding moet kunnen accepteren, wat neerkomt op het hebben van een certificaat / sleutel. De cert / sleutel kan elke zijn, b.v. zelf-ondertekend.

Zien documentatie

Vandaar dat de oplossing is:

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

3
2018-03-30 21:17



Ik vind dat dit het geaccepteerde antwoord moet zijn. Erg bedankt. - aggregate1166877


Als je absoluut zeker wilt zijn, gebruik dan aparte IP-adressen voor hosts die niet op HTTPS en hosts zouden moeten antwoorden. Dit lost ook het waarschuwingstekort "ongeldig certificaat" op.


1
2018-02-27 13:19