У меня есть Apache 2.2 с mod_ssl и несколько сайтов по HTTPS на том же IP / порту с VirtualHosting, поэтому клиент должен поддерживать SNI для подключения к этим виртуальным хостам.
Я хочу настроить свой сервер следующим образом:
Когда пользователь вводит www.dummysite.com и его браузер поддерживает SNI (указание имени сервера), любой HTTP-запрос перенаправляется на https://
где отправляется заголовок HSTS. Но если браузер не поддерживает SNI, тогда запрос обслуживается по HTTP.
Вышеупомянутое правило, изложенное как есть, на самом деле является запасным правилом для тех людей, которые все еще используют старые браузеры, поскольку у Mozilla и Chrome этой проблемы нет, просто чтобы не оставлять этих пользователей вне сайта.
Я хотел бы сделать это перенаправление на уровне конфигурации Apache, возможно, с помощью фильтра в пользовательском агенте. Я бы не хотел касаться запущенных приложений, кроме как убедиться, что нет прямых ссылок http: // (в противном случае они подразумевают предупреждение безопасности)
[Edit] (при редактировании вопроса забыл в вопрос): какой список пользовательских агентов с поддержкой SNI для перенаправления?
Поскольку SNI возникает во время установления связи SSL / TLS, невозможно обнаружить поддержку браузера, когда клиент подключается к HTTP.
Итак, вы правы; фильтр агента пользователя - единственный способ сделать это.
Большой вопрос заключается в том, хотите ли вы действовать в черном списке браузеров, которые, как вы знаете, не будут слушать SNI, или в белом списке браузеров, которые, как известно, поддерживают его. Неизвестные или новые устройства, которые не могут использовать сайт, кажется препятствием для сделки, поэтому я бы сказал, что белый список может быть лучшим вариантом.
В вашем 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]
Здесь также есть опция черного списка - имейте в виду, что это рискует отправить клиента, который не использует SNI, на сайт, требующий SNI, но, с другой стороны, отправит вправо пользователей чего-то нового, например IE 10. место:
# 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]
Существует множество браузеров. Я был довольно расплывчатым с выражениями и не охватил много браузеров - это может превратиться в настоящий кошмар для обслуживания.
Какой бы вариант вы ни выбрали .. удачи!
Мое решение таково:
# 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]
Если старый браузер без SNI пытается получить доступ https://www.example.com/* тогда он сначала выдаст ошибку в браузере, чего нельзя избежать, поскольку до тех пор, пока apache не ответит браузеру без поддержки SNI, он не знает, какой сайт запрашивает. Затем он перенаправляется на страницу, сообщающую пользователю, что его браузер слишком старый (до тех пор, пока пользователь продолжает переходить на веб-сайт).
А для пользователей с новыми браузерами у меня есть
#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]
Это исключает большинство старых браузеров, включая такие, как MSIE 5-8 в Vista (9+ - это только Vista / 7, поэтому поддерживает SNI). Это не 100% (симбиан игнорируется и т. Д.), Но должен работать для большинства. Меньшинство по-прежнему может принять ошибку сертификата.
Насколько мне известно, на самом деле нет хорошего способа сделать это - вы можете использовать правило mod_rewrite или похожие условно на основе User-agent
заголовок, но он должен быть на виртуальном хосте НЕ-SSL: если браузер не поддержка SNI, и он переходит в безопасный (https://
) сайт будет иметь поведение Apache старой школы «Вот первый SSL-сертификат, который я связал с этим IP-адресом. Надеюсь, это то, что вы хотели!» - Если это не тот сертификат, который ожидал браузер, вы получите сообщение об ошибке о несоответствии имени хоста.
По сути, это означает, что люди должны перейти на межстраничную страницу без SSL, которая будет перенаправлять их - возможно, раскрывая любые данные, которые они отправляют в своем запросе. Это может или не может быть нарушением условий сделки (вы говорите, что все равно собираетесь отправить их на сайт без SSL, если они не поддерживают SNI, поэтому я предполагаю, что вас не слишком заботит безопасность. Если бы я был при разработке системы, в которой требуется SSL в качестве уровня шифрования или аутентификации, я был бы немного настойчивее в этом ...)
Однако ничто из этого не мешает кому-то добавить в закладки безопасный сайт - и если они используют службу общих закладок или восстанавливают свои закладки на машине, на которой веб-браузер не поддерживает SNI, они снова попадают в случай потенциальных ошибок SSL. .
У меня возникнет соблазн решить это одним из трех способов:
RewriteRule
на основе User-Agent
заголовки.<SCRIPT>
тег на VHost не по умолчанию; если загрузка прошла успешно, это часть JS, которая перезагружает всю страницу по HTTPS.Из них мне лично нравится №2 больше всего, но это требует изменения кода ваших сайтов.
Просто для всех, кто в этом нуждается.
Если у вас несколько хостов и вы хотите, чтобы все они поддерживали SSL в VirtualHosting (и вы купили сертификат для каждого), попробуйте новый 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]
Использование:
<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>
Как я писал здесь, вы можете проверить только поддержку SNI предшествующий требовать этого. То есть вы не можете заставить пользователей перейти на SNI HTTPS, а затем отступить, если они его не поддерживают, потому что они получат такую ошибку (из Chrome в Windows XP) без возможности продолжить.
Поэтому (к сожалению) пользователю приходится начинать работу через небезопасное HTTP-соединение, а затем обновляться только в том случае, если он поддерживает SNI.
Вы можете обнаружить поддержку SNI через:
Удаленный скрипт
На простой HTTP-странице загрузите <script>
с вашего конечного сервера SNI HTTPS, и если сценарий загружается и работает правильно, вы знаете, что браузер поддерживает SNI.
Междоменный AJAX (CORS)
Подобно варианту 1, вы можете попробовать выполнить междоменный запрос AJAX со страницы HTTP на HTTPS, но имейте в виду, что CORS имеет только ограниченная поддержка браузера.
Понюхайте пользовательский агент
Это, вероятно, наименее надежный метод, и вам нужно будет выбрать между черным списком браузеров (и операционных систем), которые не поддерживают его, или белым списком известных систем, которые его поддерживают.
Мы знаем, что все версии IE, Chrome и Opera в Windows XP и ниже не поддерживают SNI. Видеть CanIUse.com для полного списка поддерживаемых браузеров.