web-dev-qa-db-fra.com

Rediriger vers SSL uniquement si le navigateur prend en charge SNI

J'ai Apache 2.2 avec mod_ssl et un tas de sites dans HTTPS sur la même adresse IP/Port avec VirtualHosting, de sorte que le client doit prendre en charge SNI pour se connecter à ces hôtes virtuels.

Je voudrais configurer mon serveur de la manière suivante:

Lorsqu'un utilisateur achète www.dummysite.com et son navigateur supporte Sni (indication du nom du serveur), toute demande HTTP est redirigée vers https:// Lorsqu'un en-tête HSTS est envoyé. Mais si le navigateur ne supporte pas Sni, la demande est servie par HTTP.

La règle ci-dessus, indiquée comme c'est réellement une règle de secours pour les personnes qui gèrent toujours de vieux navigateurs, comme Mozilla et Chrome pas ce problème, juste pour éviter de laisser ces utilisateurs de le site.

Je voudrais faire cela redirection au niveau de configuration Apache, peut-être avec un filtre sur l'agent utilisateur. Je ne voudrais pas toucher des applications en cours d'exécution, sauf s'assurer qu'aucun fichier http: // direct est présent (sinon, ils impliquent un avertissement de sécurité)

[Edit] (lors de la modification de la question que j'ai oubliée la Question): Quelle est la liste des agents utilisateur compatibles SNI à rediriger?

Puisque Sni se produit pendant la poignée de main SSL/TLS, il n'est pas possible de détecter le support du navigateur lorsque le client se connecte à HTTP.

Alors, tu as raison; Un filtre d'agent utilisateur est le seul moyen de le faire.

La grande question est de savoir si vous souhaitez agir sur une liste noire contre les navigateurs que vous savez n'écouteront pas pour SNI ou un blancheur de navigateurs connus pour le soutenir. Des appareils obscurs ou nouveaux incapables d'utiliser le site ressemblent à un daqueur deal, donc je dirais que la liste blanche pourrait être la meilleure option.

Dans votre 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]

Voici l'option de liste noire, gardant à l'esprit que cela dirige le risque d'envoyer un client qui n'utilise pas SNI vers un site indispensable SNI, mais d'autre part, envoyer des utilisateurs de quelque chose de nouveau comme IE 10 au bon endroit:

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

Il y a beaucoup de navigateurs là-bas. J'ai été assez lâche avec les expressions et je n'ai pas couvert de beaucoup de navigateurs - cela pourrait devenir tout à fait le cauchemar à maintenir.

Quelle que soit l'option que vous choisissez .. bonne chance!

20
Shane Madden

Ma solution est la suivante:

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

Si un ancien navigateur sans Sni tente d'accéder https://www.example.com/ * Ensuite, il lancera une erreur sur le navigateur d'abord, ce qui ne peut pas être évité depuis jusqu'à ce que Apache ne réponde à un non- SNI Navigateur Il ne sait pas quel site il demande. Ensuite, il redirige vers une page en disant à l'utilisateur que leur navigateur est trop âgé (aussi longtemps que les clics d'utilisateur continuent vers le site Web).

Et pour les utilisateurs avec de nouveaux navigateurs, j'ai

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

Cela exclut la plupart des anciens navigateurs, y compris certains comme MSIE 5-8 sur Vista (9+, Vista/7 SOIT SOIT SOUTENIR SNI). Ce n'est pas à 100% (Symbian est ignoré, etc.) mais devrait travailler pour la majorité. La minorité peut toujours choisir d'accepter l'erreur de certificat.

8
malc_b

Pour autant que je sache, il n'y a pas vraiment de bon moyen de le faire - vous pouvez utiliser une Mod_rewrite règle ou similaire conditionnellement basé sur le User-agent en-tête, mais il faudrait être sur un Vhost non SSL: si le navigateur ne le fait pas Support Sni et ça va à un (https://) Site, il va chercher le comportement de l'ancienne école Apache "Voici le premier certificat SSL que j'ai associé à cette adresse IP - espérons que c'est ce que vous vouliez!" - Si ce n'est pas le Certificat Le navigateur attendait que vous obtiendrez un message d'erreur sur les incompatibles de nom d'hôte.

Cela signifie fondamentalement que les personnes doivent toucher une page interstitielle non-SSL qui les redirigera - éventuellement exposant les données qu'ils envoient dans leur demande. Cela peut ou non être un daqueur de l'affaire (vous dites que vous allez les envoyer à un site non SSL quand même si elles ne supportent pas Sni, alors je suppose que vous ne vous souciez pas de beaucoup de sécurité. Si j'étais Concevoir un système nécessitant un besoin de SSL en tant que couche de cryptage ou d'authentification, je serais un peu plus insistant à ce sujet ...)

Aucun de cela n'empêche quelqu'un de bookmarking le site sécurisé, cependant, et s'ils utilisent un service de signet partagé ou restaurent leurs signets sur une machine où le navigateur Web ne prend pas en charge SNI, ils sont de retour dans l'affaire Potent-Errors Errors .

3
voretaq7

Je serais tenté de résoudre celui-ci de trois manières:

  1. RewriteRule basé sur User-Agent en-tête.
  2. Charger un HTTPS: // URI dans un <SCRIPT> tag sur un vhost non par défaut; Si la charge réussit, c'est un peu de JS qui recharge la page entière sous HTTPS.
  3. Apprenez à mes visiteurs à utiliser quelque chose comme HTTPS partout si cela est une priorité pour eux, forcer HTTPS sur les pages où il devrait être nécessaire et espérer que tout fonctionne à la fin.

Parmi ceux-ci, je ressemble personnellement au mieux le meilleur, mais cela implique de modifier le code de vos sites.

1
BMDan

Juste pour que quelqu'un ait besoin de ça.

Si vous avez plusieurs hôtes et souhaitez que tous ceux-ci soient activés par SSL dans VirtualHosting (et vous avez acheté un certificat pour chacun) essayez le nouveau 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]

Usage:

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