Frage Nur auf SSL umleiten, wenn der Browser SNI unterstützt


Ich habe Apache 2.2 mit mod_ssl und eine Reihe von Websites in HTTPS auf der gleichen IP / Port mit VirtualHosting, so Client muss SNI unterstützen, um eine Verbindung zu diesen virtuellen Hosts.

Ich möchte meinen Server folgendermaßen konfigurieren:

Wenn ein Benutzer www.dummysite.com und seinen Browser eingibt unterstützt SNI (Server Name Indication), wird jede HTTP-Anfrage umgeleitet https:// wo ein HSTS-Header gesendet wird. Aber wenn der Browser unterstützt nicht SNI dann wird die Anfrage von HTTP bedient.

Die obige Regel, so wie sie ist, ist eigentlich eine Ausweichregel für diejenigen Leute, die noch alte Browser betreiben, da Mozilla und Chrome dieses Problem nicht haben, nur um zu vermeiden, dass diese Benutzer die Seite verlassen.

Ich würde dies gerne auf der Apache-Konfigurationsebene tun, vielleicht mit einem Filter auf dem User-Agent. Ich möchte keine laufenden Anwendungen berühren, außer sicherzustellen, dass keine direkten http: // - Verweise vorhanden sind (andernfalls implizieren sie eine Sicherheitswarnung).

[Bearbeiten] (beim Bearbeiten der Frage, die ich vergessen habe das Frage): Was ist die Liste der SNI-fähigen Benutzeragenten, die umgeleitet werden?


19
2018-05-16 20:34


Ursprung




Antworten:


Da SNI während des SSL / TLS-Handshakes auftritt, ist es nicht möglich, die Browserunterstützung zu erkennen, wenn der Client eine Verbindung mit HTTP herstellt.

Also hast du recht; Ein User-Agent-Filter ist die einzige Möglichkeit, dies zu tun.

Die große Frage ist, ob Sie auf einer Blacklist gegen Browser agieren wollen, von denen Sie wissen, dass sie nicht auf SNI warten, oder eine Whitelist von Browsern, von denen bekannt ist, dass sie diese unterstützen. Obskure oder neue Geräte, die die Site nicht nutzen können, scheinen ein Deal-Breaker zu sein, also würde ich sagen, dass die Whitelist die bessere Option ist.

In Ihrem 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]

Hier ist auch die Blacklist-Option - bedenke, dass dies das Risiko birgt, einen Client zu senden, der SNI nicht an eine SNI-benötigte Site sendet, aber auf der anderen Seite Benutzer von etwas Neuem wie IE 10 nach rechts schickt Platz:

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

Es gibt viele Browser da draußen. Ich war ziemlich locker mit den Ausdrücken und habe nicht viele Browser behandelt - das könnte sich zu einem Albtraum entwickeln, den man beibehalten sollte.

Welche Option Sie auch wählen .. Viel Glück!


20
2018-05-16 20:58



Großartig! Ich habe mit Opera Mobile getestet (SNI-konform, aber nicht in der Liste) und es wird nicht umgeleitet. Mit meinem Firefox wird es umgeleitet! - usr-local-ΕΨΗΕΛΩΝ
Ich empfehle, diese Lösung mit der BrowserMatch-Direktive von mod_setenvif zu modularisieren httpd.apache.org/docs/2.2/mod/mod_setenvif.html . Verwenden Sie BrowserMatch, um eine Umgebungsvariable supports_sni = y festzulegen, und schreiben Sie RewriteCond% {ENV: supports_sni} = y. Auf diese Weise können Sie die SNI-Erkennungslogik für alle anderen RewriteRules wiederverwenden. - 200_success
@ 200_success Gute Idee! - Shane Madden♦


Meine Lösung ist das:

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

Wenn ein alter Browser ohne SNI versucht zuzugreifen https://www.example.com/* Dann wird zuerst ein Fehler auf den Browser geworfen, was nicht vermieden werden kann, bis Apache auf einen Nicht-SNI-Browser antwortet, der nicht weiß, welche Seite er fragt. Dann wird auf eine Seite umgeleitet, die dem Benutzer mitteilt, dass sein Browser zu alt ist (solange der Benutzer auf die Website klickt).

Und für Benutzer mit neuen Browsern habe ich

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

Das schließt die meisten alten Browser aus, einschließlich MSIE 5-8 unter Vista (9+ ist nur Vista / 7, unterstützt also SNI). Es ist nicht 100% (Symbian wird ignoriert usw.), sollte aber für die Mehrheit funktionieren. Die Minderheit kann weiterhin den Zertifikatfehler akzeptieren.


8
2017-10-10 16:21





Soweit mir bekannt ist, gibt es nicht wirklich einen guten Weg, dies zu tun - Sie können eine verwenden mod_rewrite-Regel oder ähnliches bedingt basierend auf User-agent Header, aber es müsste auf einem NON-SSL-vhost sein: Wenn der Browser nicht unterstütze SNI und es geht zu einem sicheren (https://) Site wird es das Old-School-Apache-Verhalten von bekommen "Hier ist das erste SSL-Zertifikat, das ich mit dieser IP-Adresse verknüpft habe - Ich hoffe, es ist das, was Sie wollten!" - Wenn es sich nicht um das Zertifikat handelt, das der Browser erwartet hat, erhalten Sie eine Fehlermeldung über fehlende Hostnamen.

Dies bedeutet im Grunde, dass Nutzer auf eine Interstitial-Seite ohne SSL zugreifen müssen, die sie umleiten wird. Dabei werden möglicherweise alle Daten angezeigt, die sie in ihrer Anfrage senden. Dies kann ein Deal-Breaker sein oder auch nicht (Sie sagen, dass Sie sie sowieso auf eine Nicht-SSL-Site schicken werden, wenn sie SNI nicht unterstützen, also nehme ich an, dass Ihnen Sicherheit wenig wichtig ist. Wenn ich es wäre Ich habe ein System entworfen, das SSL als Verschlüsselungs- oder Authentifizierungsschicht benötigt. Ich würde aber ein bisschen dringender darüber sein ...)

Nichts davon hindert jemanden daran, die sichere Site zu bookmarken - und wenn sie einen geteilten Bookmark-Dienst verwenden oder ihre Lesezeichen auf einem Rechner wiederherstellen, auf dem der Web-Browser SNI nicht unterstützt, sind sie zurück im Fall von potentiellen SSL-Fehlern .


3
2018-05-16 20:48





Ich wäre versucht, diesen einen von drei Wegen zu lösen:

  1. RewriteRule beyogen auf User-Agent Kopfzeilen.
  2. Laden Sie einen https: // URI in a <SCRIPT> Tag auf einem nicht standardmäßigen VHost; Wenn der Ladevorgang erfolgreich ist, lädt JS die gesamte Seite unter HTTPS neu.
  3. Weisen Sie meine Besucher an, etwas wie HTTPS Everywhere zu verwenden, wenn dies eine Priorität für sie ist, erzwingen Sie HTTPS auf Seiten, wo es erforderlich sein sollte, und hoffen Sie, dass am Ende alles funktioniert.

Von diesen mag ich persönlich # 2 am besten, aber das bedeutet, dass Sie den Code Ihrer Websites ändern müssen.


1
2018-05-16 20:55





Nur für jeden, der es braucht.

Wenn Sie mehrere Hosts haben und möchten, dass alle in VirtualHosting SSL-fähig sind (und Sie für jedes ein Zertifikat gekauft haben), versuchen Sie es mit dem neuen 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]

Verwendungszweck:

<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
2018-05-16 22:36





Wie ich hier gepostet habe, Sie können nur die SNI-Unterstützung testen vorher es zu verlangen. Das heißt, Sie können Benutzer nicht auf SNI HTTPS zwingen und dann zurückfallen, wenn sie dies nicht unterstützen, da sie einen Fehler wie diesen (von Chrome unter Windows XP) erhalten, ohne dass sie fortfahren können.

Also (leider) muss der Benutzer tatsächlich über eine unsichere HTTP-Verbindung neu starten und dann nur aktualisiert werden, wenn er SNI unterstützt.

Sie können die SNI-Unterstützung über Folgendes erkennen:

  1. Remote-Skript
    Laden Sie auf Ihrer einfachen HTTP-Seite a <script> von Ihrem SNI-HTTPS-Zielserver und wenn das Skript korrekt geladen und ausgeführt wird, wissen Sie, dass der Browser SNI unterstützt.

  2. Domänenübergreifendes AJAX (CORS)
    Ähnlich wie bei Option 1 könnten Sie versuchen, eine domainübergreifende AJAX-Anfrage von der HTTP-Seite an HTTPS auszuführen, aber beachten Sie, dass CORS dies getan hat nur eingeschränkte Browserunterstützung.

  3. Sniff den User-Agent
    Dies ist wahrscheinlich die am wenigsten zuverlässige Methode, und Sie müssen entscheiden, ob eine Blacklist von Browsern (und Betriebssystemen) bekannt ist, die es nicht unterstützt, oder eine Whitelist bekannter Systeme, die dies tun.

    Wir wissen, dass alle Versionen von IE, Chrome & Opera unter Windows XP und darunter keine SNI unterstützen. Sehen CanIUse.com für eine vollständige Liste der unterstützten Browser.


0
2017-09-06 05:30