Проблемы безопасности SSL SNI
Просто интересно, полезен ли SNI для отделения публичного контента от частного. Мне удалось настроить наш сервер для обслуживания /foo
для каждого клиента, но служить /bar
только для клиентов из интрасети, указав имя хоста, которое разрешается только из интрасети.
Таким образом, конфиг выглядит так: (раздел очень важная часть)
NameVirtualHost *:443
# JkWorkersFile must be global so including it here
JkWorkersFile workers.properties
<VirtualHost *:443>
ServerName public.foo.com
JkMountFile uriworkermap-pub.properties
</VirtualHost>
<VirtualHost *:443>
ServerName private-foo
JkMountFile uriworkermap-priv.properties
</VirtualHost>
<VirtualHost *:443>
ServerName 10.1.2.3
JkMountFile uriworkermap-priv.properties
</VirtualHost>
Подвох, если вы добавите это имя в свой hosts
файл для разрешения на общедоступный IP-адрес, тогда SNI фактически разрешит обработать его так же, как если бы это был действительный запрос из интрасети.
Я обдумывал мысли об использовании только числового IP вместо имен (например, 10.1.2.3
) но я предполагаю, что то же самое можно обмануть, если клиент имеет тот же IP в своей собственной подсети (например, хост Linux, который перенаправляет порты на общедоступный IP моего веб-сервера.
Узел находится за брандмауэром, на который я не имею влияния. У него только один IP (внутренний), но при необходимости я могу сделать два.
Практический вопрос: как предотвратить такую утечку? С помощью htaccess например? Указывая разные IP-адреса? Или нет другого способа, кроме как создать отдельный экземпляр сервера и забыть SNI?
2 ответа
Если вам нужно ограничить содержание в зависимости от происхождения посетителей сайта, вы используете эту информацию в качестве основного элемента управления доступом (а не только имя ресурса, который вы пытаетесь защитить).
С Apache 2.2 это было бы Allow
Директива.
<VirtualHost *:443>
ServerName private-foo
<Location />
Order Deny,Allow
Deny from all
# Allow from the internal subnet 10.1.2.0/24
Allow from 10.1.2
</Location>
...
Часто в вашем сценарии сервер будет иметь внутренний и общедоступный IP-адрес, и поскольку внутренние пользователи будут использовать только этот внутренний IP-адрес, вы будете привязывать виртуальный хост только к этому внутреннему IP-адресу, например <VirtualHost 10.1.2.3:443>
вместо того, чтобы слушать все IP
Кроме того, ваше замечание, касающееся.htaccess, вызвало мою любимую мозоль, процитированное из руководства по файлам .htaccess:
Вам следует избегать использования файлов.htaccess полностью, если у вас есть доступ к файлу конфигурации основного сервера httpd. Использование файлов.htaccess замедляет работу вашего http-сервера Apache. Любая директива, которую вы можете включить в файл.htaccess, лучше задать в
Directory
блок в основном файле конфигурации Apache, так как он будет иметь тот же эффект с лучшей производительностью.
То, что вы пробуете, называется "безопасность через неизвестность" - вы на самом деле не защитили ресурс, вы просто надеетесь, что никто не узнает, как его искать, если только они не изнутри вашей компании.
Кроме того, SNI не имеет ничего общего с этой проблемой. У вас возникла бы точно такая же проблема, если бы контент передавался по HTTP без каких-либо сертификатов, и вы пытались заблокировать контент, скрывая его с использованием отдельных имен хостов.
Это на самом деле не безопасно.
Если вы хотите сохранить доступ к ресурсу, вы должны сделать это другим способом. Одним из способов может быть установка отдельного экземпляра сервера на отдельный IP и использование брандмауэров для защиты этого экземпляра. Другой вариант - использовать блок на основе IP на виртуальном сервере, содержащем ограниченный контент, или каталог. Или вы можете комбинировать это с требованием от клиента использовать сертификат, выданный вашим внутренним центром сертификации, если он у вас есть. Или почти любой другой способ сочетания аутентификации с авторизацией.
Но надеяться, что никто за пределами вашей компании не будет пытаться использовать "секретное" имя хоста, не является верной мерой безопасности, используете ли вы SSL/SNI или нет.