Weiterleitung zu SSL nur, wenn der Browser SNI unterstützt

20

Ich habe Apache 2.2 mit mod_ssl und eine Reihe von Sites in HTTPS auf derselben IP / demselben Port wie 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 und sein Browser unterstützt SNI (Server Name Indication) wird jede HTTP - Anforderung umgeleitet , https://wo ein HSTS - Header gesendet wird. Wenn der Browser jedoch kein SNI unterstützt, wird die Anforderung über HTTP bereitgestellt.

Die oben genannte Regel ist eine Fallback-Regel für Benutzer, 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, möglicherweise mit einem Filter auf dem Benutzeragenten. Ich möchte laufende Anwendungen nur berühren, wenn sichergestellt ist, dass keine direkten http: // -Referenzen vorhanden sind (andernfalls wird eine Sicherheitswarnung angezeigt).

[Bearbeiten] (während der Frage bearbeite ich vergaß die Frage): Was ist die Liste der SNI-fähige Benutzeragenten zu umleiten?

usr-local-ΕΨΗΕΛΩΝ
quelle

Antworten:

20

Da SNI während des SSL / TLS-Handshakes auftritt, kann keine Browserunterstützung erkannt werden, wenn der Client eine Verbindung zu HTTP herstellt.

Also hast du recht; Ein Benutzeragentenfilter ist die einzige Möglichkeit, dies zu tun.

Die große Frage ist, ob Sie auf einer Blacklist gegen Browser vorgehen möchten, von denen Sie wissen, dass sie nicht auf SNI warten, oder auf einer 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, daher würde ich sagen, dass die Whitelist die bessere Option sein könnte.

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, der SNI nicht verwendet, an eine von SNI benötigte Site zu senden, aber andererseits Benutzer von etwas Neuem wie IE 10 nach rechts schickt 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 abgedeckt - dies könnte zu einem Albtraum werden.

Für welche Option Sie sich auch entscheiden. Viel Glück!

Shane Madden
quelle
1
Groß! Ich habe mit Opera Mobile (das zwar SNI-kompatibel ist, aber nicht in der Liste enthalten ist) getestet und es leitet nicht weiter. Mit meinem Firefox leitet es weiter!
usr-local-ΕΨΗΕΛΩΕΨΗΕΛ
6
Ich empfehle, diese Lösung mit der BrowserMatch-Direktive von mod_setenvif httpd.apache.org/docs/2.2/mod/mod_setenvif.html zu modularisieren . Verwenden Sie BrowserMatch, um eine Umgebungsvariable support_sni = y festzulegen, und schreiben Sie dann RewriteCond% {ENV: support_sni} = y. Auf diese Weise können Sie die SNI-Erkennungslogik für alle anderen möglicherweise vorhandenen RewriteRules wiederverwenden.
200_erfolg
@ 200_success Gute Idee!
Shane Madden
8

Meine Lösung lautet:

  # 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 ausgelöst, der nicht vermieden werden kann, da Apache erst auf einen Nicht-SNI-Browser antwortet, den es nicht kennt nach welcher Seite es fragt. Dann wird zu einer Seite weitergeleitet, die dem Benutzer mitteilt, dass sein Browser zu alt ist (solange der Benutzer auf die Website klickt).

Und für User 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]

Dies schließt die meisten alten Browser aus, einschließlich einiger wie 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.

malc_b
quelle
3

Soweit mir bekannt ist, gibt es keine gute Möglichkeit, dies zu tun. Sie können eine mod_rewrite-Regel oder ähnliches verwenden , die auf dem User-agentHeader basiert , aber es müsste sich auf einem NON-SSL-vhost befinden: Wenn der Browser dies nicht tut SNI unterstützen und es geht zu einer sicheren ( https://) Site, die das Apache-Verhalten der alten Schule erhält: "Hier ist das erste SSL-Zertifikat, das ich mit dieser IP-Adresse verknüpft habe - ich hoffe, es ist das, was Sie wollten!" - Wenn dies nicht das Zertifikat ist, das der Browser erwartet hat, erhalten Sie eine Fehlermeldung, dass die Hostnamen nicht übereinstimmen.

Dies bedeutet im Grunde, dass Benutzer eine Nicht-SSL-Interstitial-Seite aufrufen müssen, die sie umleitet - und möglicherweise alle Daten offenlegt, die sie in ihrer Anfrage senden. Dies kann ein Deal Breaker 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 ja Wenn ich ein System entwerfe, für das SSL als Verschlüsselungs- oder Authentifizierungsschicht benötigt wird, wäre ich etwas beharrlicher ...)

Nichts davon hindert jemanden daran, die sichere Site mit einem Lesezeichen zu versehen - und wenn er einen gemeinsam genutzten Lesezeichendienst verwendet oder seine Lesezeichen auf einem Computer wiederherstellt, auf dem der Webbrowser SNI nicht unterstützt, ist er wieder im Fall von potenziellen SSL-Fehlern .

voretaq7
quelle
1

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

  1. RewriteRulebasierend auf User-AgentÜberschriften.
  2. Laden Sie einen https: // URI in ein <SCRIPT>Tag auf einem nicht standardmäßigen VHost. Wenn der Ladevorgang erfolgreich ist, lädt JS die gesamte Seite unter HTTPS neu.
  3. Bringen Sie meinen Besuchern bei, HTTPS Everywhere zu verwenden, wenn dies für sie Priorität hat, und zwingen Sie HTTPS auf Seiten, auf denen dies erforderlich sein sollte, und hoffen Sie, dass am Ende alles funktioniert.

Von diesen mag ich persönlich # 2 am liebsten, aber dazu gehört es, den Code Ihrer Websites zu ändern.

BMDan
quelle
0

Nur für alle, die es brauchen.

Wenn Sie mehrere Hosts haben und möchten, dass alle in VirtualHosting SSL-fähig sind (und Sie für jeden Host ein Zertifikat gekauft haben), probieren Sie den neuen aus 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>
usr-local-ΕΨΗΕΛΩΝ
quelle
0

Wie ich hier gepostet habe , können Sie den SNI-Support nur testen, bevor Sie ihn benötigen. Das heißt, Sie können Benutzer nicht dazu zwingen, SNI HTTPS zu verwenden und dann auf diese zurückzugreifen, wenn sie dies nicht unterstützen, da sie eine solche Fehlermeldung erhalten (von Chrome unter Windows XP), ohne dass Sie fortfahren können.

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

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

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

  2. Domänenübergreifendes 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 eingeschränkte Browser-Unterstützung bietet .

  3. Schnüffeln des Benutzeragenten
    Dies ist wahrscheinlich die am wenigsten zuverlässige Methode, und Sie müssen sich entscheiden, ob Sie eine schwarze Liste von Browsern (und Betriebssystemen) haben, die diese nicht unterstützen, oder eine Whitelist bekannter Systeme, die dies tun.

    Wir wissen, dass alle Versionen von IE, Chrome & Opera unter Windows XP und darunter SNI nicht unterstützen. Unter CanIUse.com finden Sie eine vollständige Liste der unterstützten Browser .

Simon East
quelle