Reindirizzare a SSL solo se il browser supporta SNI


20

Ho Apache 2.2 con mod_ssl e un sacco di siti in HTTPS sullo stesso IP / porta con VirtualHosting, quindi il client deve supportare SNI per connettersi a quegli host virtuali.

Vorrei configurare il mio server nel modo seguente:

Quando un utente digita www.dummysite.com e il suo browser supporta SNI (Server Name Indication), qualsiasi richiesta HTTP viene reindirizzata a https://dove viene inviata un'intestazione HSTS. Ma se il browser non supporta SNI, la richiesta è servita da HTTP.

La regola di cui sopra, dichiarata così com'è, è in realtà una regola di fallback per quelle persone che usano ancora vecchi browser, poiché Mozilla e Chrome non hanno questo problema, solo per evitare di lasciare questi utenti fuori dal sito.

Vorrei fare questo reindirizzamento a livello di configurazione di Apache, magari con un filtro sul programma utente. Non vorrei toccare le applicazioni in esecuzione se non assicurandomi che non siano presenti riferimenti diretti http: // (altrimenti implicano un avviso di sicurezza)

[Modifica] (durante la modifica della domanda ho dimenticato la domanda): qual è l'elenco di agenti utente abilitati SNI da reindirizzare?

Risposte:


20

Poiché SNI si verifica durante l'handshake SSL / TLS, non è possibile rilevare il supporto del browser quando il client si connette a HTTP.

Quindi hai ragione; un filtro agente utente è l'unico modo per farlo.

La grande domanda è se vuoi agire su una lista nera contro i browser che sai non ascolteranno SNI o una whitelist di browser che sono noti per supportarla. Oscuri o nuovi dispositivi che non sono in grado di utilizzare il sito sembrano un rompicapo, quindi direi che la whitelist potrebbe essere l'opzione migliore.

Nel tuo HTTP <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]

Ecco anche l'opzione blacklist: tieni presente che ciò comporta il rischio di inviare un client che non utilizza SNI a un sito necessario per SNI, ma d'altra parte invierà gli utenti di qualcosa di nuovo come IE 10 a destra posto:

# 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]

Ci sono molti browser là fuori. Sono stato piuttosto libero con le espressioni e non ho coperto molti browser - questo potrebbe trasformarsi in un vero incubo da mantenere.

Qualunque opzione scegliate .. buona fortuna!


1
Grande! Ho provato con Opera Mobile (che è conforme a SNI ma non nell'elenco) e non reindirizza. Con il mio Firefox, reindirizza!
usr-local-ΕΨΗΕΛΩΝ

6
Suggerisco di modulare questa soluzione con la direttiva BrowserMatch da mod_setenvif httpd.apache.org/docs/2.2/mod/mod_setenvif.html . Utilizzare BrowserMatch per impostare una variabile di ambiente supports_sni = y, quindi scrivere RewriteCond% {ENV: supports_sni} = y. In questo modo, puoi riutilizzare la logica di rilevamento SNI per qualsiasi altra RewriteRules che potresti avere.
200_successo

@ 200_success Buona idea!
Shane Madden

8

La mia soluzione è questa:

  # 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]

Se un vecchio browser senza SNI tenta di accedere a https://www.example.com/ *, genererà prima un errore sul browser, che non può essere evitato dal momento che Apache non risponde a un browser non SNI che non conosce quale sito sta chiedendo. Quindi reindirizza a una pagina che dice all'utente che il suo browser è troppo vecchio (fintanto che i clic dell'utente continuano sul sito Web).

E per gli utenti con nuovi browser che ho

  #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]

Ciò esclude la maggior parte dei vecchi browser, inclusi alcuni come MSIE 5-8 su Vista (9+ è solo Vista / 7, quindi supporta SNI). Non è al 100% (symbian viene ignorato ecc.) Ma dovrebbe funzionare per la maggior parte. La minoranza può ancora scegliere di accettare l'errore del certificato.


3

Per quanto ne so non c'è davvero un buon modo per farlo - Puoi usare una regola mod_rewrite o simile in modo condizionale basato sull'intestazione User-agent, ma dovrebbe essere su un vhost NON SSL: Se il browser non lo fa supporta SNI e va su un https://sito sicuro ( ) otterrà il comportamento Apache della vecchia scuola di "Ecco il primo certificato SSL che ho associato a quell'indirizzo IP - Spero che sia quello che volevi!" - Se questo non è il certificato previsto dal browser, verrà visualizzato un messaggio di errore relativo alla mancata corrispondenza del nome host.

Questo in pratica significa che le persone devono colpire una pagina interstiziale non SSL che li reindirizzerà, eventualmente esponendo tutti i dati che inviano nella loro richiesta. Questo potrebbe o meno essere un problema (si dice che li invierai comunque a un sito non SSL se non supportano SNI, quindi presumo che non ti interessi molto della sicurezza. Se lo fossi progettando un sistema che avesse bisogno di SSL come livello di crittografia o autenticazione, sarei un po 'più insistente a riguardo ...)

Niente di tutto ciò impedisce a qualcuno di aggiungere un segnalibro al sito protetto, tuttavia, e se utilizzano un servizio di segnalibri condiviso o ripristinano i segnalibri su una macchina in cui il browser Web non supporta SNI, tornano nel caso Potenziali errori SSL .


1

Sarei tentato di risolvere questo in tre modi:

  1. RewriteRulebasato sulle User-Agentintestazioni.
  2. Carica un Uttps: // URI in un <SCRIPT>tag su un VHost non predefinito; se il caricamento ha esito positivo, è un po 'di JS che ricarica l'intera pagina in HTTPS.
  3. Insegna ai miei visitatori a usare qualcosa come HTTPS Everywhere se questa è una priorità per loro, imponi HTTPS su pagine dove dovrebbe essere richiesto e spero che alla fine tutto vada bene.

Di questi, personalmente mi piace il secondo, il migliore, ma ciò comporta la modifica del codice dei tuoi siti.


0

Solo per chiunque ne abbia bisogno.

Se hai più host e desideri che tutti siano abilitati per SSL in VirtualHosting (e hai acquistato un certificato per ciascuno) prova il nuovo 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]

Uso:

<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

Come ho pubblicato qui , è possibile verificare il supporto SNI solo prima di richiederlo. Cioè, non è possibile forzare gli utenti su HTTPS SNI e quindi ripiegare se non lo supportano, perché riceveranno un errore come questo (da Chrome su Windows XP) senza alcun modo di procedere.

Quindi (purtroppo) l'utente deve effettivamente ricominciare da una connessione HTTP non sicura e quindi essere aggiornato solo se supporta SNI.

È possibile rilevare il supporto SNI tramite:

  1. Script remoto
    Dalla tua semplice pagina HTTP, carica un <script>server HTTPS SNI di destinazione e se lo script viene caricato ed eseguito correttamente, sai che il browser supporta SNI.

  2. AJAX tra domini (CORS)
    Simile all'opzione 1, potresti provare a eseguire una richiesta AJAX tra domini dalla pagina HTTP a HTTPS, ma tieni presente che CORS ha un supporto browser limitato .

  3. Annusare l'agente utente
    Questo è probabilmente il metodo meno affidabile e dovrai decidere se avere una lista nera di browser (e sistemi operativi) noti per non supportarlo, o una lista bianca di sistemi noti che lo fanno.

    Sappiamo che tutte le versioni di IE, Chrome e Opera su Windows XP e versioni precedenti non supportano SNI. Vedi CanIUse.com per l'elenco completo dei browser supportati .

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.