nginx: Tam olarak adlandırılmış bir SSL sunucu bloğunun, tüm SSL'ler için catchall işlevi görmesi nasıl önlenir


17

Birçok sanal sunuculu bir web sunucum var. Bunlardan yalnızca 1 tanesi SSL'dir. Sorun, SSL'yi dinleyen bir catchall sunucu bloğu olmadığından, diğer sitelere yönelik herhangi bir https isteği 1 SSL bloğu tarafından sunulur.

Konfigürasyonum aslında şöyle görünüyor:

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

Şimdi 443 için varsayılan bir dinleyici olmadığından https://server1.com, server2.comhttps bloğu tarafından sunulan bir istek sonuçlanacak . Bu mantığını izler server_namede docs.

Eşleşme yoksa, yapılandırma dosyasındaki bir sunucu {...} bloğu aşağıdaki sıraya göre kullanılır:

  1. [varsayılan | default_server] olarak işaretlenmiş eşleşen dinleme yönergesine sahip sunucu bloğu
  2. eşleşen bir dinleme yönergesine sahip ilk sunucu bloğu (veya üstü kapalı dinleme 80;)

Bu sorun için tercih edilen çözüm nedir? 443'ü dinleyebilmem ve kötü istekleri işleyebilmem için tüm sunucu bloğumu yakalama için kukla sertifika ayarlamam gerekiyor mu? Farkında olmadığım bir ana bilgisayar adı eşleşmesine zorlayan bir parametre var mı server?


Kullanıcılar https kullanarak diğer sitelere erişmeye çalıştıklarında ne olmak istersiniz?
David Schwartz

İdeal olarak, nginx'in ana bilgisayar adı eşleşmediği sürece https sunmamasını veya aynı ana bilgisayarda http'ye yönlendirmesini isterim.
numaraları1311407

Yanıtlar:


9

İdeal olarak, nginx'in ana bilgisayar adı eşleşmediği sürece https sunmamasını veya aynı ana bilgisayarda http'ye yönlendirmesini isterim.

İkisi de mümkün değil. Https://foo.example.com/ adresine giden bir istemciden bağlantı , adlarından biri olarak "foo.example.com" içeren bir SSL sertifikası dışında hiçbir şey tarafından kabul edilemez. SSL bağlantısı kabul edilene kadar yeniden yönlendirme fırsatı yoktur.

Her siteyi SSL için yapılandırırsanız, sertifika hatasını tıklayan bir kullanıcı istediği siteyi alır. SSL için yalnızca bir hata sayfası sağlayan bir "tümünü yakala" sitesi yapılandırır ve SSL'yi desteklemesi gereken bir site için ad tabanlı sanal barındırma yapılandırırsanız, istemcilere bir hata sayfası sunabilirsiniz.

SSL ve HTTP sanal barındırma birlikte güzel oynamıyor.


Dokümanları okuduktan sonra topladım. Sadece birţeyi özlememi umuyordum. SSL uyarılarını hiç umursamıyorum. Birisinin server1.com'a girmesini ve kendilerini server2.com ana sayfasına bakmasını istemiyorum ... Nginx'e bir isteği kabul etmemesini söylemenin gerçekten bir yolu yok mu?
numbers1311407

İsteği kabul etmezse, ilk site çalışmaz. Kullanıcının hangi siteye erişmeye çalıştığını bulma isteğini kabul etmesi gerekir.
David Schwartz

2
" Foo.example.com adresine giden bir istemciden bağlantı , adlarından biri olarak" foo.example.com "bulunan bir SSL sertifikası dışında hiçbir şey tarafından kabul edilemez." - Bu doğru değildir, sunucu isteği kabul eder ve istenen DN'nin sunucu sertifikası DN ile eşleştiğini doğrulamak istemciye bağlıdır.
ColinM

4

Bunu yapmanın tek yolu, kendinden imzalı bir SSL sertifikası oluşturmak ve bu sertifikayı gelen https isteklerinde kontrol kazanmak için kullanmaktır. Kendinden imzalı SSL sertifikanızı bu yayında özetlenen birkaç basit adımda oluşturabilirsiniz .

Diyelim ki server.crt dosya adına sahip kendinden imzalı bir sertifika oluşturdunuz. Daha sonra nginx yapılandırmanıza aşağıdakileri eklersiniz:

server {
    listen  443;

    ssl    on;
    ssl_certificate         /etc/nginx/ssl/server.crt;
    ssl_certificate_key     /etc/nginx/ssl/server.key;

    server_name server1.com;

    keepalive_timeout 60;
    rewrite ^       http://$server_name$request_uri? permanent;
}

Yine de tarayıcı SSL uyarı mesajını alacaksınız, ancak en azından bir sonraki adımda kontrol sahibi olacaksınız.


1
Buna katılıyorum. Tarayıcının güvenilmeyen sertifikalar hakkında bir uyarı mesajı göstermesi sorunu var, ancak yalnızca kullanıcıların https: // <ip-adresi> adresine gitmesini ve sunucuya gerçek hayaletlerinizden biri için eşit derecede geçersiz bir sertifika almasını engellemeye çalışıyorsanız (geçersiz çünkü ana makine adı eşleşmez), kendilerine geçersiz bir kendinden imzalı kukla sertifika sunmak daha iyidir. Bu tür onlara "burada görülecek hiçbir şey yok, başka bir sunucudan gelen bir sertifika bile yok" der.
Daniel F

2

Tümünü yakala sunucu bloğu ve dönüş durum kodu 444 ekleyin. Herhangi bir veri göndermeden önce nginx'e bağlantıyı kapatmasını söyler.

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

1

Bu günlerde TLS Sunucu Adı Gösterimi uzantısını (SNI, RFC 6066) kullanabilirsiniz. HTTPS dinleyicisi, uygun sertifikayı sunmadan önce alan adını tanıyabilecektir.

Bu, TÜM etki alanlarınız için sertifikalara sahip olmanız gerektiği anlamına gelir ve SNI diğer etki alanlarından birini tanımak için kullanıldığında, sunucu adı gereken tek biriyle eşleşmediği sürece HTTP 301 yönlendirmesini HTTP şifrelenmemiş sürümüne kullanabilirsiniz. şifreleme.

SNI hakkında daha fazla bilgi nginx belgelerinde bulunabilir http://nginx.org/en/docs/http/configuring_https_servers.html


0

İstenen ana makine adını http {}bloktaki geçerli ana makine adlarıyla eşleyin :

map $ssl_server_name $correct_hostname_example {
  default 0;
  example.com 1;
  www.example.com 1;
}

Ve sonra server {}blokta yanlış ana bilgisayar adıyla bağlantıları öldürün:

if ($correct_hostname_example = 0) {
  return 444;
}

Birden çok sunucu bloğu için gerektiğinde birden çok harita kullanın. Bağlantı yine de sertifikalarınızdan biri kullanılarak kurulacaktır, ancak bu son blok SSL sunan her sunucu bloğunda mevcutsa, geçersiz ana makine adlarıyla bağlantıları "engelleyeceksiniz". Yalnızca ilk sunucu bloğunda gerekli olabilir, ancak her sunucu bloğuna eklenmesi siparişin önemli olmamasını sağlar.

$ssl_server_nameDeğişken nginx 1.7 veya daha fazlası bulunur.


0

Sorunu şu şekilde çözdüm:

  1. Kendinden imzalı sertifika oluştur:

openssl req -nodes -x509 -newkey rsa:4096 -keyout self_key.pem -out self_cert.pem -days 3650

  1. NginX'in bulabileceği yere kopyalayın:

cp self*.pem /etc/nginx/ssl/

  1. Tümünü yakalama yolu oluşturun:
server {
    listen 443 default_server ssl;

    ssl on;
    ssl_certificate /etc/nginx/ssl/self_cert.pem;
    ssl_certificate_key /etc/nginx/ssl/self_key.pem;

    return 301 http://$host;
}

Bu ne yapar: kendi sertifikası olmayan herhangi bir sunucuda size bir uyarı (etrafında bir yol yok) verecektir, ancak uyarı yanlış sertifika adını söylemez. Kullanıcı "yine de ziyaret et" i tıklarsa, yazdıkları sitenin SSL olmayan sürümüne yönlendirilir.

uyarı :

SLL özellikli siteniz yalnızca tanımlıysa www.example.com(değil example.com) tanımlarsa, tümünü yakala rotanız https://example.comotomatik olarak imzalanan sertifika ve ilgili uyarıyla sunulur.


-2

Http:

server {
    listen       443;
    server_name  *.com;
    rewrite        ^ http://$host$request_uri? permanent;
}    

Dönüş 404 :

server {
    listen       443;
    server_name  *.com;
    return 404;
}    

1
SSL tünelinin herhangi bir HTTP yönlendirmesi gerçekleşmeden önce gerçekleşmesi gerektiğinden, bu yine de bir SSL uyarısı ile sonuçlanır. David Schwartz'ın kabul edilen cevabına bakın.
cjc
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.