it-swarm.asia

Nginx'te, alt etki alanını korurken tüm http isteklerini https'ye nasıl yeniden yazabilirim?

Web sunucumdaki tüm http isteklerini https istekleri olarak yeniden yazmak istiyorum, aşağıdakilerle başladım:

 sunucu {
 dinle 80; 
 
 konum/{
 yeniden yazma ^ (. *) https: //mysite.com$1 kalıcı; 
} 
 ... 


Bir Sorun, bunun herhangi bir alt alan bilgisini (ör. Node1.mysite.com/folder) kaldırmasıdır, her şeyi https'ye yönlendirmek ve alt alan adını korumak için yukarıdakileri nasıl yeniden yazabilirim?

517
MikeN

Yeni nginx sürümlerinde doğru yol

Bu soruya ilk cevabımın belli bir zamanda doğru olduğu ortaya çıktı, ancak başka bir tuzağa dönüştü - güncel kalmak için lütfen kontrol edin Yeniden yazma tuzaklarını vergilendirme

Birçok SE kullanıcısı tarafından düzeltildim, bu yüzden kredi onlara gidiyor, ancak daha da önemlisi, doğru kod:

server {
       listen         80;
       server_name    my.domain.com;
       return         301 https://$server_name$request_uri;
}

server {
       listen         443 ssl;
       server_name    my.domain.com;
       # add Strict-Transport-Security to prevent man in the middle attacks
       add_header Strict-Transport-Security "max-age=31536000" always; 

       [....]
}
758
Saif Bechan

NOT: Bunu yapmanın en iyi yolu https://serverfault.com/a/401632/3641 - tarafından sağlandı, ancak burada tekrarlandı:

server {
    listen         80;
    return 301 https://$Host$request_uri;
}

En basit durumda Ana Makineniz, göndermek istediğiniz hizmetiniz olarak sabitlenecektir - bu, tarayıcıya 301 yönlendirmesi yapar ve tarayıcı URL'si buna göre güncellenir.

Aşağıda regex nedeniyle verimsiz olan önceki cevap, basit bir 301 @kmindi tarafından gösterildiği gibi harika

Ben nginx 0.8.39 ve üstü kullanıyorum ve aşağıdakileri kullandım:

 server {
       listen 80;
       rewrite ^(.*) https://$Host$1 permanent;
 }

İstemciye kalıcı bir yönlendirme gönderir.

280
Michael Neale

Bence en iyi ve tek yol böyle bir HTTP 301 Kalıcı Olarak Taşındı yönlendirme kullanmak olmalıdır:

server {
    listen         [::]:80;
    return 301 https://$Host$request_uri;
}

HTTP 301 Kalıcı Olarak Taşındı yönlendirmesi de en etkili olanıdır, çünkü daha önce bahsedilen şekilde değerlendirilecek herhangi bir normal ifade yoktur pitfails .


Yeni HTTP 308 Kalıcı Olarak Taşındı İstek yöntemini koruyor ve büyük tarayıcılar tarafından destekleniyor . Örneğin, 308, tarayıcıların yönlendirme isteği için istek yöntemini POST yerine GET olarak değiştirmesini önler.


ana bilgisayar adını ve alt etki alanını korumak istiyorsanız, yol budur.

Yerel olarak da kullandığım için bu DNS yoksa hala çalışır. Örneğin http://192.168.0.100/index.php ve tam olarak https://192.168.0.100/index.php.

Kullanırım listen [::]:80 Sunucumda _ olduğu için bindv6onlyfalse olarak ayarlandığından ipv4 soketine de bağlanır. bunu listen 80 IPv6 istemiyorsanız veya başka bir yere bağlamak istiyorsanız.

Saif Bechan'in çözümü server_name benim durumumda localhost ama bir ağ üzerinden ulaşılamaz.

Michael Neale'nin çözümü iyi, ancak pitfails'e göre, yönlendirme 301 ile daha iyi bir çözüm var;)

125
kmindi

Sunucu bloğunda aşağıdakileri de yapabilirsiniz:

# Force HTTPS connection. This rules is domain agnostic
if ($scheme != "https") {
    rewrite ^ https://$Host$uri permanent;
}
22
Oriol

Yukarıdakiler her zaman yeni alt alan adlarının oluşturulmasıyla işe yaramadı. Örneğin. Yaklaşık 30 alt alan adı için AAA.example.com BBB.example.com.

Sonunda aşağıdakilerle çalışan bir yapılandırma var:

server {
  listen 80;
  server_name _;
  rewrite ^ https://$Host$request_uri? permanent;
}
server {
  listen  443;
  server_name example.com;
  ssl on;
  ssl_certificate /etc/ssl/certs/myssl.crt;
  ssl_certificate_key /etc/ssl/private/myssl.key;
  ssl_prefer_server_ciphers       on;
# ...
# rest of config here
# ...
}
17
Aleck Landgraf

Uzun, çok uzun zaman önce çok önemli bir düzeltmeyle doğru cevaba bir yorum gönderdim, ancak bu düzeltmeyi kendi cevabında vurgulamak gerektiğini hissediyorum. Herhangi bir noktada güvenli olmayan HTTP kurulumu yapmış ve kullanıcı içeriği bekliyorsanız, formlarınız varsa, bir API barındırıyorsanız veya herhangi bir web sitesini, aracı, uygulamayı veya yardımcı programı konuşacak şekilde yapılandırdıysanız, önceki yanıtların hiçbiri güvenli değildir. siteniz.

Sunucunuza bir POST isteği yapıldığında sorun oluşur. Sunucu düz bir 30x yönlendirme POST içerik kaybolacak. Ne olur tarayıcı/istemci isteği SSL'ye yükseltir ancak eski sürüme geçirin = bir POST isteğine GET. POST parametreleri kaybolacak ve sunucunuza yanlış istekte bulunacak.

Çözüm basit. Bir HTTP 1.1 307 yönlendirme. Bu RFC 7231 S6.4.7'de ayrıntılı olarak açıklanmıştır:

  Note: This status code is similar to 302 (Found), except that it
  does not allow changing the request method from POST to GET.  This
  specification defines no equivalent counterpart for 301 (Moved
  Permanently) ([RFC7238], however, defines the status code 308
  (Permanent Redirect) for this purpose).

Kabul edilen çözümden uyarlanan çözüm 307 yönlendirme kodunuzda:

server {
       listen         80;
       server_name    my.domain.com;
       return         307 https://$server_name$request_uri;
}

server {
       listen         443 ssl;
       server_name    my.domain.com;
       # add Strict-Transport-Security to prevent man in the middle attacks
       add_header Strict-Transport-Security "max-age=31536000"; 

       [....]
}
6
Mahmoud Al-Qudsi

AWS ELB arkasında ngnix çalıştırıyorum. ELB, http üzerinden ngnix ile konuşuyor. ELB'nin istemcilere yönlendirmeler göndermesinin bir yolu olmadığından, X-Forwarded-Proto üstbilgisini kontrol edip yeniden yönlendiriyorum:

if ($http_x_forwarded_proto != 'https') {
    return 301 "https://www.exampl.com";
}
4
MANCHUCK

Ben böyle yapmayı başardım:

server {
listen 80;
listen 443 ssl;

server_name domain.tld www.domain.tld;

# global HTTP handler
if ($scheme = http) {
        return 301 https://www.domain.tld$request_uri;
}

# global non-WWW HTTPS handler
if ($http_Host = domain.tld){
        return 303 https://www.domain.tld$request_uri;
}
}

https://stackoverflow.com/a/36777526/6076984

4
stamster

80 numaralı bağlantı noktasında varsayılan yanıt olarak return 301 https://$Host$request_uri; Yaparsanız, sunucunuz er ya da geç açık proxy'lerin listesine girebilir [1] ve İnternet'te başka bir yere trafik göndermek için kötüye kullanılmaya başlayabilir. Günlükleriniz bunun gibi mesajlarla dolarsa, bunun size olduğunu biliyorsunuz:

42.232.104.114 - - [25/Mar/2018:04:50:49 +0000] "GET http://www.ioffer.com/i/new-fashion-fine-gold-bracelet-versaec-bracelet-641175733 HTTP/1.1" 301 185 "http://www.ioffer.com/" "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0; Hotbar 4.1.8.0; RogueCleaner; Alexa Toolbar)"

Sorun şu ki, $Host, Tarayıcının Host üstbilgisinde ne gönderdiğini, hatta HTTP açılış satırındaki ana makine adını, bunun gibi tekrarlar:

GET http://www.ioffer.com/i/new-fashion-fine-gold-bracelet-versaec-bracelet-641175733 HTTP/1.1

Bu sorun nedeniyle, diğer bazı yanıtlar $server_name Yerine $Host Kullanılmasını önermektedir. $server_name Her zaman server_name Bildirimine ne koyduğunuza göre değerlendirir. Ancak orada birden fazla alt alanınız varsa veya joker karakter kullanıyorsanız, bu işe yaramaz, çünkü $server_name Yalnızca girişinden sonra ilk girişini kullanır server_name Bildirimi ve daha da önemlisi bir joker karakteri yankılayacak (genişletmeyecek).

Peki güvenliği korurken birden fazla alanı nasıl destekleyebilirim? Kendi sistemlerimde bu ikilemi ilk önce default_server Kullanmayan bir $Host Bloğunu listeleyerek ele aldım. ] ve ardından şunları yapan bir joker karakter bloğunu listeler:

server {
  listen 80 default_server;
  server_name example.com;
  return 301 https://example.com$request_uri;
}
server {
  listen 80;
  server_name *.example.com;
  return 301 https://$Host$request_uri;
}

(İkinci blokta birden fazla alan da listeleyebilirsiniz.)

Bu kombinasyonla eşleşmeyen alanlar sabit kodlu bir yere yönlendirilir (her zaman example.com) Ve kendi alanınızla eşleşen alanlar doğru yere gider. Sunucunuz açık bir proxy olarak yararlı olmaz, bu nedenle sorun yaşamayacaksınız.

Eğer huysuz hissediyorsanız, meşru alanlarınızın default_server Blok eşleşmesini hiçbiri yapabileceğinizi ve rahatsız edici bir şey sunabileceğinizi varsayalım. . . .

[1] Teknik olarak "proxy" yanlış Word'dür, çünkü sunucunuz dışarı çıkıp istemciler için istekleri yerine getirmez, sadece bir yönlendirme gönderir, ancak doğru Word'ün ne olacağından emin değilim. Ayrıca hedefin ne olduğundan emin değilim, ancak günlüklerinizi gürültü ile dolduruyor ve CPU'nuzu ve bant genişliğinizi tüketiyor, bu yüzden de buna bir son verebilirsiniz.

1
Paul A Jungwirth

Görünüşe göre kimse bunu% 100 doğru anlamadı. 80 numaralı bağlantı noktasının tüm web sunucusu için 443 eşdeğerine gitmesini sağlamak için tümünü yakala özelliğini belirtmek için sunucu_adı yönergesini değil, listen yönergesini kullanmanız gerekir isim. Ayrıca bakınız https://nginx.org/en/docs/http/request_processing.html

sunucu {
 dinle 80 varsayılan; 
 dinle [::]: 80 varsayılan; 
 dönüş 307 https: // $ Sunucu $ request_uri; 
} 
  • $ Host alt alan adlarını yakalar.
  • 307 ve 308, hem POST ve GET isteği URI'larını içerir.
  • 307 Geçici, ayrıntılı testten sonra Kalıcı 308 olarak değiştirin:

Ve zaten /etc/nginx/conf.d/ içinde ne olduğunu kontrol ettiğinizden emin olun çünkü daha sık olarak default.conf'un varolan bazı hayaletleri döndürdüğü sorunlar yaşadım. Nginx sorunları ile çalışma sırası her zaman varsayılan dosyayı dışarı taşıyarak, nerede yanlış gittiğini görmek için satır satır yorum yaparak koyarak başlıyor.

0
Julius