fragen stichworte

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

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

Ich möchte meinen Server folgendermaßen konfigurieren:

Wenn ein Benutzer www.dummysite.com eingibt und sein Browser SNI (Server Name Indication) unterstützt, werden alle HTTP-Anforderungen an https:// umgeleitet, wo ein HSTS-Header gesendet wird. Wenn der Browser jedoch keine SNI unterstützt, wird die Anforderung über HTTP bereitgestellt.

Die obige Regel ist eine Fallback-Regel für diejenigen, die noch alte Browser verwenden, da Mozilla und Chrome dieses Problem nicht haben, nur um zu vermeiden, dass diese Benutzer von der Website ausgeschlossen werden.

Ich möchte diese Umleitung auf der Apache-Konfigurationsebene durchführen, vielleicht mit einem Filter auf dem Benutzeragenten. Ich möchte keine laufenden Anwendungen berühren, es sei denn, es sind keine direkten Verweise auf http://vorhanden (andernfalls implizieren sie eine Sicherheitswarnung)

[Bearbeiten] (während der Bearbeitung der Frage der -Frage wurde vergessen): Was ist die Liste der SNI-fähigen Benutzeragenten, die umgeleitet werden sollen?

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 zu HTTP herstellt.

Also, du hast 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 auf 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 - bedenken Sie, dass dies das Risiko birgt, einen Client zu senden, der SNI nicht an eine von SNI benötigte Site sendet, aber andererseits Benutzer von etwas Neuem wie IE 10 sendet an den richtigen Ort:

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

Meine Lösung ist dies:

# 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, auf https://www.example.com/ * zuzugreifen, wird zuerst ein Fehler im Browser angezeigt, der nicht vermieden werden kann, bis Apache auf a antwortet Nicht-SNI-Browser weiß es nicht, welche Website es verlangt. 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 einiger 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.

Soweit mir bekannt ist, gibt es keine gute Möglichkeit, dies zu tun. Sie können eine mod_rewrite-Regel oder eine ähnliche -bedingt verwenden, die auf dem User-agent -Header basiert. Es müsste sich jedoch auf einem NON-SSL-Vhost befinden: Wenn der Browser nicht SNI unterstützt und er zu einer sicheren (https://) - Site geht, erhält er das Apache-Verhalten der alten Schule "Hier ist das erste SSL-Zertifikat, das ich mit dieser IP-Adresse verknüpft habe - ich hoffe, es ist genau das, was Sie wollten!" - Wenn es sich nicht um das Zertifikat handelt, das der Browser erwartet hat, wird eine Fehlermeldung angezeigt, dass der Hostname nicht übereinstimmt.

Dies bedeutet im Grunde, dass die Benutzer auf eine Nicht-SSL-Interstitial-Seite klicken müssen, auf der sie weitergeleitet werden. Dabei werden möglicherweise alle Daten, die sie in ihrer Anfrage senden, offengelegt. Dies kann ein Dealbreaker sein oder auch nicht (Sie sagen, Sie werden sie sowieso an eine Nicht-SSL-Site senden, wenn sie SNI nicht unterstützen. Ich gehe also davon aus, dass Sie sich nicht so sehr um die Sicherheit kümmern. Wenn ich wäre Wenn Sie ein System entwickeln, das SSL als Verschlüsselungs- oder Authentifizierungsschicht benötigt, würde ich diesbezüglich etwas beharrlicher sein ...)

Dies hindert jedoch niemanden daran, die sichere Site mit einem Lesezeichen zu versehen. Wenn sie einen gemeinsam genutzten Lesezeichendienst verwenden oder ihre Lesezeichen auf einem Computer wiederherstellen, auf dem der Webbrowser SNI nicht unterstützt, befinden sie sich wieder im Potential-for-SSL -Erspiegelt den Fall.

Ich wäre versucht, diese drei Möglichkeiten zu lösen:

  1. RewriteRule basiert auf User-Agent -Heatern.
  2. Laden Sie einen https://URI in einem <SCRIPT> -Tag auf einem nicht standardmäßigen VHost. Wenn das Laden erfolgreich ist, lädt JS die gesamte Seite unter HTTPS neu.
  3. Bringen Sie meinen Besuchern bei, so etwas wie HTTPS Everywhere zu verwenden, wenn dies für sie eine Priorität darstellt, erzwingen Sie HTTPS auf Seiten, auf denen dies erforderlich sein sollte, und hoffen Sie, dass am Ende alles klappt.

Davon mag ich persönlich # 2 am besten, aber dazu muss der Code Ihrer Websites geändert werden.

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 jeweils ein Zertifikat gekauft haben), versuchen Sie das neue 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]

Verwendung:

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

Wie ich hier gepostet habe, können Sie nur die SNI-Unterstützung vor testen, wenn dies erforderlich ist. Das heißt, Sie können Benutzer nicht zu SNI HTTPS erzwingen und dann zurückgreifen, wenn sie es nicht unterstützen, da sie eine solche Fehlermeldung (von Chrome unter Windows XP) erhalten, ohne dass Sie fortfahren können.

Daher muss der Benutzer (leider) tatsächlich über eine unsichere HTTP-Verbindung beginnen und dann nur dann ein Upgrade durchführen, wenn er SNI unterstützt.

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

  1. Remote-Skript
    Laden Sie von Ihrer normalen HTTP-Seite ein <script> von Ihrem SNI-HTTPS-Zielserver. Wenn das Skript ordnungsgemäß geladen und ausgeführt wird, wissen Sie, dass der Browser SNI unterstützt.

  2. Domainübergreifender AJAX (CORS)
    Ähnlich wie bei Option 1 können Sie versuchen, eine domänenübergreifende AJAX-Anforderung von der HTTP-Seite an das HTTPS auszuführen. Beachten Sie jedoch, dass CORS nur eine eingeschränkte Browserunterstützung hat.

  3. Ermitteln Sie den Benutzeragenten
    Dies ist wahrscheinlich die am wenigsten zuverlässige Methode, und Sie müssen sich entscheiden, ob Sie eine Blacklist mit Browsern (und Betriebssystemen) haben, von denen bekannt ist, dass sie sie nicht unterstützt, oder eine Whitelist mit bekannten Systemen, die dies tun.

    Wir wissen, dass alle Versionen von IE, Chrome & amp; Opera unter Windows XP und darunter unterstützt kein SNI. Eine vollständige Liste der unterstützten Browser finden Sie unter CanIUse.com.