Https için “varsayılan” nginx sunucusunu doğru şekilde ayarlamak


70

Aynı makinede çalışan bazı sunucular var, bazıları yalnızca http, bazıları hem http, hem de https. Ana yapılandırma dosyasında bulunan ayrı dosyalarda tanımlanmış birkaç sunucu bloğu vardır.

Diğer yapılandırma dosyalarındaki diğer sunucu_adılarından hiçbiriyle eşleşmeyen isteklere genel bir "bakım sayfası" sunacak olan http için "varsayılan" bir sunucu kurdum. Http varsayılan sunucusu beklendiği gibi çalışır, sunucu_adı "_" kullanır ve içerdiği listede ilk sırada yer alır (çünkü sunucular arasında yinelenen sunucu_adı olması durumunda, ilk önce görünenin kullanıldığını gözlemledim). Bu harika çalışıyor.

Aynı tam sunucu bloğunu beklerdim (sadece "80'i varsayılan_ayarı dinle" yi "443 varsayılan_ınıver dinle" ve ayrıca "dönüş 444'ü" yerine sayfa döndürmek yerine) değiştirirdim. Bunun yerine, yeni varsayılan https sunucusunun gerçekte gelen tüm https bağlantılarını alıp, başarısız olmasına neden olmasına rağmen, diğer sunucu blokları gelen istekler için daha uygun sunucu_isimlerine sahip görünüyor. Yeni varsayılan https sunucusunu kaldırmak yarı-doğru davranışın devam etmesine neden olacaktır: https'li web siteleri tamamen doğru yüklenecektir; ancak https içermeyen web sitelerinin tümü, içerme dosyalarındaki ilk https sunucusuna yönlendirilir (bu, "default_server" görünmezse belgelere göre, sonra görünen ilk sunucu bloğu "varsayılan" olur).

Öyleyse sorum şu, ssl bağlantıları için nginx'te bir "varsayılan sunucu" tanımlamanın doğru yolu nedir? Neden açıkça bir "default_server" ayarladığımda açgözlülük ve tüm bağlantıları kaparken nginx'in "varsayılan sunucu" 'nun beklediğim gibi çalıştığına karar vermeme izin verdiğimde (yanlış sunucu varsayılan ve diğer gerçek sunucular olarak ayarlanmışken) doğru davranmak)?

İşte benim "varsayılan sunucular". Http, diğer sunucuları bozmadan çalışır. Https diğer sunucuları kırar ve hepsini tüketir.

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;
    }
}

Aranızda neyin yanlış olabileceğini gördünüz mü?

ssl  https  nginx 

Yanıtlar:


27

"Default" https bloğunuzda tanımlanmış herhangi bir ssl_certificate veya ssl_certificate_key anahtarınız yok. Bu varsayılan senaryo için gerçek bir anahtara sahip olmasanız da istemeseniz de, bir tanesini yapılandırmanız gerekir, aksi halde nginx tanımladığınız istenmeyen davranışa sahip olacaktır.

Ortak Adla * ile kendinden imzalı bir sertifika oluşturun ve bunu config'inize bağlayın; istediğiniz şekilde çalışmaya başlayacaktır.

Bu kurulum altındaki "varsayılan" davranış, bir tarayıcının bir istisna olarak sertifikayı eklemesi durumunda, bağlantının nginx tarafından kesileceği ve tarayıcılarının varsayılan olduğunu göreceği takdirde, tarayıcının sertifikanın güvenilir olamayacağına dair bir uyarı alması olur. "bağlanamadı" hata mesajı.


1
Bunu denedim ama hala çalışmıyor: IP'ye gelen tüm ssl istekleri diğer ssl ana bilgisayarıma gider. Deneyebileceğim başka bir şey var mı?
Michael Härtl

22

Tek bir IP üzerinde nginx ile paylaşılan paylaşılan bir barındırma yapılandırmayı başardım. Varsayılan HTTP ve HTTPS gelen bilinmeyen alanlar için bir 404 hizmet vermektedir.

1 - Varsayılan bölge oluşturma

Nginx ascii sırayla vhosts yüklüyor, 00-defaultiçine bir dosya / sembolik bağlantı oluşturmanız gerekir /etc/nginx/sites-enabled.

2 - Varsayılan bölgeyi doldur

00-defaultVarsayılan vhosts ile doldurun . İşte kullanıyorum bölge:

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 - Kendinden imzalı sertifika oluşturma, test etme ve yeniden yükleme

İçine kendinden imzalı bir sertifika oluşturmanız gerekecek /etc/nginx/ssl/nginx.crt.

Varsayılan bir kendinden imzalı sertifika oluşturun:

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

Sadece bir hatırlatıcı:

  • Yeniden yüklemeden / yeniden başlatmadan önce nginx yapılandırmasını test edin: nginx -t
  • Bir keyfi yeniden yükleyin: sudo service nginx reload

Umarım yardımcı olur.


2
Güvenli olmayan bir siteyi ziyaret eden tarayıcı uyarısını çözmez.
gdbj

4
Bir catch-all herhangi bir domain ile eşleşmeli diye çözülemez. Hiçbir SSL tüm etki alanlarının joker karakterini oluşturamaz. Sunucunuzda google.fr adresini taklit ediyorsanız, sunucunuzu google.fr olarak doğrulayabileceğinizi hayal edin. Ciddi bir güvenlik sorunu olurdu :(
olmazsa

Ya, sanırım bu mantıklı. Ne yazık ki, Chrome'da, sunucunun trafiği reddetmesinden daha kötü olan 404 sayfasını görmeden önce size korkunç bir uyarı verilir. Sunucunun yanlış yapılandırılmış gibi görünmesini sağlar.
gdbj

Çok teşekkür ederim. Bu benim için çalıştı, default_server443'ü dinlemek zorunda kalmam dışında , IPv6 adresini [::]: 80 ve [::]: 443'ü ekledim default_server.
chmike

16

Temelde, config dosyamızdaki ilk sunucu tanımının SSL bağlantıları için her şeyi yakalayan bir sunucu olarak sunulmasından kaçınılmasını istiyoruz. Bunu hepimiz biliyoruz (http'e ve güzel çalışan default_server config kullanıyorsanız).

Bu, SSL için bildirimsel olarak gerçekleştirilemez (henüz) bu nedenle bir IF ile kodlamamız gerekiyor ...

Değişken $host, istek satırından veya http başlığından ana bilgisayar adıdır. Değişken $server_name, şu anda bulunduğumuz sunucu bloğunun adıdır.

Eğer bu ikisi eşit değilse, o zaman engellenmesi gereken başka bir ana bilgisayar için bu SSL sunucu bloğunu görev yaptınız.

Kod, sunucunuzun IP adreslerine özel referanslar içermediğinden, değişiklik yapmadan diğer sunucu yapılandırmaları için kolayca yeniden kullanılabilir.

Örnek:

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;
    }

    ...

Ne yaptığını açıklayabilir misin listen [::]:443 ssl http2;? Bunun için dokümantasyon bulmakta sorun yaşıyorum.
Andrew Brown

Sanırım buldum, ne arayacağımı bilmem gerekiyordu. IPV4 ve IPV6 yönergeleri.
Andrew Brown

7

Radmilla Mustafa'nın cevabını daha ayrıntılı olarak anlatmak için:

Nginx, server_name eşlemesi için 'Host' başlığını kullanır. TLS SNI kullanmaz. Bu, bir SSL sunucusu için, nginx'in sertifika / anahtara sahip olan SSL bağlantısını kabul edebilmesi gerektiği anlamına gelir. Sertifika / anahtar herhangi biri olabilir, örneğin kendinden imzalı.

Belgelere bakın

Dolayısıyla, çözüm:

server {
    server_name _;
    listen 80 default_server;
    listen 443 ssl default_server;

    ## To also support IPv6, uncomment this block
    # listen [::]:80 default_server;
    # listen [::]:443 ssl default_server;

    ssl_certificate <path to cert>;
    ssl_certificate_key <path to key>;
    return 404; # or whatever
}

Bunun kabul edilen cevap olması gerektiğini düşünüyorum. Çok teşekkürler.
aggregate1166877

2

Bu konuda benim kadar saç kaybına uğrayan herkese (bugün bunu neredeyse tüm gün geçirdi). Neredeyse her şeyi denedim ve sonunda doğru bir şekilde çalışmasını sağlayan şey şu aptal çizgi idi:

ssl_session_tickets off;

Buna dayanarak , çalışmayan örneğim :

server {
    listen 443 ssl http2 default_server;
    listen [::]:443 ssl http2 default_server;
    server_name _;

    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key /etc/nginx/ssl/nginx.key;
    ssl_session_tickets off;

    return 404;
}

Bunun neden gerekli olduğu hakkında hiçbir fikrim yok, bundan türettiğim ilke nginx'in istediği şeyi vermediğimizde çok garip davrandığıydı.


1
sen bir efsanesin.
Nizar Sarışın

1

Kesinlikle emin olmak istiyorsanız, HTTPS'de cevap vermemesi gereken ana bilgisayarlar ve olması gereken ana bilgisayarlar için ayrı IP adresleri kullanın. Bu ayrıca "geçersiz sertifika" tarayıcı uyarısı sorununu da çözer.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.