SSL'ye yalnızca tarayıcı SNI'yi destekliyorsa yönlendirme


20

Mod_ssl ile Apache 2.2 ve VirtualTosting ile aynı IP / bağlantı noktasında HTTPS sitelerinde bir sürü var, bu yüzden istemci bu sanal ana bilgisayarlara bağlanmak için SNI desteklemesi gerekir.

Sunucumu şu şekilde yapılandırmak istiyorum:

Bir kullanıcı www.dummysite.com yazdığında ve tarayıcısı SNI'yi (Sunucu Adı Gösterimi) desteklediğinde , herhangi bir HTTP isteği https://bir HSTS başlığının gönderildiği yere yönlendirilir . Ancak tarayıcı SNI'yi desteklemiyorsa , istek HTTP tarafından sunulur.

Yukarıdaki kural, olduğu gibi, aslında hala eski tarayıcıları çalıştıran kişiler için bir geri dönüş kuralıdır, çünkü Mozilla ve Chrome bu sorunu sadece bu kullanıcıları siteden çıkarmaktan kaçınmak için yoktur.

Bu yönlendirme, belki de kullanıcı aracısı üzerinde bir filtre ile Apache yapılandırma düzeyinde yapmak istiyorum. Hiçbir doğrudan http: // referansları (aksi takdirde bir güvenlik uyarısı ima) mevcut olduğundan emin olmak dışında çalışan uygulamalara dokunmak istemiyorum

(Unutmuşum soru düzenlerken [Düzenle] soruyu): yönlendirmek için SNI etkin kullanıcı ajanlarının listesi nedir?

Yanıtlar:


20

SNI, SSL / TLS anlaşması sırasında oluştuğundan, istemci HTTP'ye bağlandığında tarayıcı desteğini algılamak mümkün değildir.

Yani haklısın; bunu yapmanın tek yolu kullanıcı aracısı filtresidir.

Büyük soru, kara listede, SNI'yi dinlemeyeceğini bildiğiniz tarayıcılara veya onu desteklediği bilinen tarayıcıların beyaz listesine karşı hareket etmek isteyip istemediğinizdir. Karanlık veya yeni cihazların siteyi kullanamaması bir anlaşma kırıcı gibi görünüyor, bu yüzden beyaz listenin daha iyi bir seçenek olabileceğini söyleyebilirim.

HTTP'nizde <VirtualHost>:

# Internet Explorer 7, 8, 9, on Vista or newer
RewriteCond %{HTTP_USER_AGENT} MSIE\s7.*Windows\sNT\s6 [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE\s8.*Windows\sNT\s6 [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE\s9.*Windows\sNT\s6 [OR]
# Chrome on Windows, Mac, Linux
RewriteCond %{HTTP_USER_AGENT} Windows\sNT\s6.*Chrome [OR]
RewriteCond %{HTTP_USER_AGENT} Macintosh.*Chrome [OR]
RewriteCond %{HTTP_USER_AGENT} Linux.*Chrome [OR]
# Firefox - we'll just make the assumption that all versions in the wild support:
RewriteCond %{HTTP_USER_AGENT} Gecko.*Firefox
RewriteRule ^/(.*)$ https://ssl.hostname/$1 [R=301]

Kara liste seçeneği de burada - bunun SNI kullanmayan bir istemciyi SNI gerekli bir siteye gönderme riski taşıdığını, ancak diğer taraftan IE 10 gibi yeni bir şeyin kullanıcılarını sağa göndereceğini unutmayın. yer:

# IE 6
RewriteCond %{HTTP_USER_AGENT} !MSIE\s6
# Windows XP/2003
RewriteCond %{HTTP_USER_AGENT} !Windows\sNT\s5
# etc etc
RewriteRule ^/(.*)$ https://ssl.hostname/$1 [R=301]

Dışarıda bir sürü tarayıcı var. İfadeler ile oldukça gevşek oldum ve çok fazla tarayıcı ele almadım - bu bakım yapmak için kabusa dönüşebilir.

Hangi seçeneği seçerseniz seçin .. iyi şanslar!


1
Harika! Opera Mobile (SNI uyumlu ancak listede olmayan) ile test ettim ve yönlendirmiyor. Firefox'umla yönlendiriyor!
usr-local-ΕΨΗΕΛΩΝ

6
Bu çözümü mod_setenvif httpd.apache.org/docs/2.2/mod/mod_setenvif.html adresindeki BrowserMatch yönergesi ile modüle etmenizi öneririm . Support_sni = y ortam değişkenini ayarlamak için BrowserMatch kullanın, ardından RewriteCond% {ENV: supports_sni} = y yazın. Bu şekilde, sahip olabileceğiniz diğer RewriteRules için SNI algılama mantığını yeniden kullanabilirsiniz.
200_success

@ 200_success İyi fikir!
Shane Madden

8

Benim çözümüm şudur:

  # Test if SNI will work and if not redirect to too old browser page
  RewriteCond %{HTTPS} on
  RewriteCond %{SSL:SSL_TLS_SNI} =""
  RewriteRule ^ http://www.example.com/too-old-browser [L,R=307]

SNI'sız eski bir tarayıcı https://www.example.com/ * adresine erişmeye çalışırsa , önce tarayıcıda bir hata atar; bu, apache SNI olmayan bir tarayıcıya yanıt verene kadar önlenemez. hangi siteyi istediği. Ardından, kullanıcıya tarayıcılarının çok eski olduğunu bildiren bir sayfaya yönlendirir (kullanıcı tıklamaları web sitesine devam ettiği sürece).

Yeni tarayıcıları olan kullanıcılar için

  #Test if new browser and if so redirect to https
  #new browser is not MSIE 5-8, not Android 0-3
  RewriteCond %{HTTPS} off
  RewriteCond %{HTTP_USER_AGENT} !MSIE\ [5-8]
  RewriteCond %{HTTP_USER_AGENT} !Android.*(Mobile)?\ [0-3]
  RewriteRule ^ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]

Vista'da MSIE 5-8 gibi bazı eski tarayıcıların çoğu hariçtir (9+ sadece Vista / 7'dir, bu nedenle SNI'yi destekler). % 100 değildir (Symbian yok sayılır vb.) Ama çoğunluk için çalışmalıdır. Azınlık yine de sertifika hatasını kabul etmeyi seçebilir.


3

Bildiğim kadarıyla bunu yapmanın gerçekten iyi bir yolu yok - Başlığa dayalı olarak mod_rewrite kuralı veya benzeri bir koşul kullanabilirsiniz User-agent, ancak NON-SSL olmayan bir hayalette olması gerekir: Tarayıcı yapmazsa SNI'yi destekliyor ve güvenli bir ( https://) siteye gidiyor, "İşte bu IP adresiyle ilişkilendirdiğim ilk SSL sertifikası - Umarım istediğin budur!" - Tarayıcının beklediği sertifika bu değilse, ana makine adı uyuşmazlıkları hakkında bir hata mesajı alırsınız.

Bu, temel olarak kullanıcıların kendilerini yönlendirecek SSL dışı bir geçiş reklamı sayfası kullanması gerektiği anlamına gelir - muhtemelen isteklerinde gönderdikleri verileri açığa çıkarır. Bu bir anlaşma kırıcı olabilir veya olmayabilir (SNI'yi desteklemiyorlarsa zaten SSL olmayan bir siteye göndereceğinizi söylüyorsunuz, bu yüzden güvenlik konusunda bu kadar umursamadığınızı varsayıyorum. şifreleme veya kimlik doğrulama katmanı olarak SSL'ye ihtiyaç duyan bir sistem tasarlamak olsa da, bu konuda biraz daha ısrarcı olurdum ...)

Bunların hiçbiri birisinin güvenli siteye yer işareti koymasını engellemez - ve paylaşılan bir yer imi hizmeti kullanırlarsa veya yer imlerini web tarayıcısının SNI'yi desteklemediği bir makineye geri yüklerse, SSL-Potansiyel-Hata Durumuna geri döner .


1

Bunu üç yoldan birini çözme cazibesine kapılırdım:

  1. RewriteRuledayalı User-Agentbaşlıklarından.
  2. <SCRIPT>Varsayılan olmayan bir VHost'taki etikete bir https: // URI yükleyin; yükleme başarılı olursa, tüm sayfayı HTTPS altında yeniden yükleyen bir miktar JS.
  3. Ziyaretçilerime HTTPS Everywhere gibi bir şey kullanmalarını öğretin, eğer bu onlar için bir öncelikse, HTTPS'yi gerekli olması gereken sayfalarda zorlayın ve sonunda her şeyin yolunda gittiğini umun.

Bunlardan ben şahsen # 2 en iyi gibi, ama bu sitelerinizin kodunu değiştirmeyi içerir.


0

Sadece ihtiyacı olan herkes için.

Birden fazla ana bilgisayarınız varsa ve bunların VirtualHosting'de SSL etkin olmasını istiyorsanız (ve her biri için bir sertifika satın aldıysanız) yeni mod_djechelon_ssl

$ cat /etc/apache2/mod_djechelon_ssl.conf 
RewriteEngine on
# Internet Explorer 7, 8, 9, on Vista or newer
RewriteCond %{HTTP_USER_AGENT} MSIE\s7.*Windows\sNT\s6 [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE\s8.*Windows\sNT\s6 [OR]
RewriteCond %{HTTP_USER_AGENT} MSIE\s9.*Windows\sNT\s6 [OR]
# Chrome on Windows, Mac, Linux
RewriteCond %{HTTP_USER_AGENT} Windows\sNT\s6.*Chrome [OR]
RewriteCond %{HTTP_USER_AGENT} Macintosh.*Chrome [OR]
RewriteCond %{HTTP_USER_AGENT} Linux.*Chrome [OR]
# Firefox - we'll just make the assumption that all versions in the wild support:
RewriteCond %{HTTP_USER_AGENT} Gecko.*Firefox [OR]
#Safari iThing
RewriteCond %{HTTP_USER_AGENT} Mozilla.*iPhone.*Safari [OR]
RewriteCond %{HTTP_USER_AGENT} Mozilla.*iPod.*Safari [OR]
RewriteCond %{HTTP_USER_AGENT} Mozilla.*iPad.*Safari [OR]
RewriteRule ^/(.*)$ https://%{HTTP_HOST}/$1 [R=permanent,L]

Kullanımı:

<VirtualHost ip:80>
ServerName www.yourhost.com

Include /path/to/mod_djechelon_ssl.conf

[plain old Apache directives]
</VirtualHost>

<VirtualHost ip:443>
ServerName www.yourhost.com

[SSL-related directives]

[Copy and paste directives from above host]
</VirtualHost>

0

Burada gönderdiğim gibi , SNI desteğini yalnızca gerekmeden önce test edebilirsiniz . Yani, kullanıcıları SNI HTTPS'ye zorlayamaz ve desteklemezlerse geri çekilemezsiniz, çünkü devam etmenin bir yolu olmadan böyle bir hata alırlar (Windows XP'de Chrome'dan).

Bu nedenle (maalesef) kullanıcının aslında güvenli olmayan bir HTTP bağlantısı üzerinden başlaması ve daha sonra yalnızca SNI'yi desteklemesi durumunda yükseltilmesi gerekir.

SNI desteğini şu yollarla tespit edebilirsiniz:

  1. Uzak komut dosyası
    Düz HTTP sayfanızdan, <script>hedef SNI HTTPS sunucunuzdan a yükleyin ve komut dosyası doğru bir şekilde yüklenir ve çalışırsa, tarayıcının SNI'yi desteklediğini bilirsiniz.

  2. Web Alanları Arası AJAX (CORS)
    Seçenek 1'e benzer şekilde, HTTP sayfasından HTTPS'ye bir web alanları arası AJAX isteği gerçekleştirmeyi deneyebilirsiniz, ancak CORS'nin yalnızca sınırlı tarayıcı desteği olduğunu unutmayın .

  3. Kullanıcı-aracı koklama
    Bu muhtemelen en az güvenilir yöntemdir ve desteklemediği bilinen tarayıcıların (ve işletim sistemlerinin) kara listesine sahip olması veya bunu yapan bilinen sistemlerin bir beyaz listesi arasında karar vermeniz gerekir.

    Windows XP ve altındaki tüm IE, Chrome ve Opera sürümlerinin SNI'yi desteklemediğini biliyoruz. Desteklenen tarayıcıların tam listesi için CanIUse.com adresine bakın .

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.