Информационная безопасность

индекс
289,97

TLS/SSL изнутри, а также почему нельзя настроить HTTPS для виртуальных хостов.

TLS (что есть Transport Layer Security), он же ранее известный как SSL (Secure Sockets Layer), на данный момент является стандартом де-факто для защиты протоколов транспортного уровня от различных методов вмешательства извне. Мало кто его не использует, но не уверен что все хорошо представляют себе, как оно на самом деле работает и какими возможностями обладает, кроме банального «как же, оно ведь шифрует канал между клиентом и сервером».


Протокол SSL разрабатывался компанией Netscape, целью его разработки являлось обеспечение безопасности данных, передаваемых на транспортном уровне модели ISO/OSI. Последняя версия протокола — SSL 3.0 была опубликована в 1996 году, и послужила основой для разработки протокола TLS, которой занялась организация IETF, и результатом этой работы стал RFC 2246: The TLS protocol, version 1.0, опубликованный в 1999 году. На данный момент опубликован RFC 5246: The TLS protocol, version 2.0, который несколько расширяет функциональность первой версии, впрочем оставляя суть неизменной.

Функционирует TLS поверх транспортного протокола, например (и зачастую) TCP. Грубо говоря, он работает с двумя потоками данных, вне зависимости от их природы, — входящим и исходящим, и каждый из них преобразует в соответствующим образом зашифрованный поток (правда, тут точнее будет говорить «измененный», поскольку TLS разрешает и отсутствие шифрования передаваемых данных).

Работа протокола разделяется на два этапа: обмен ключами, и дальнейший обмен данными.
Первый этап проходит без каких-либо «полезных» данных, передаваемых от клиента к серверу и обратно, и служит для идентификации клиента и сервера, а также выбора алгоритмов и инициализации ключей для дальнейшего шифрования. На втором этапе идет просто обмен данными через установленное логическое соединение, где каждый пакет полезных данных шифруется (если шифрование включено), защищается при помощи MAC, и передается другой стороне через нижележащий протокол (TCP).
Перейдем к более подробному описанию первой части протокола, как наиболее важной.
Инициализируется общение между клиентом и сервером сообщением ClientHello, которое посылается клиентом серверу. В этом сообщении клиент перечисляет поддерживаемые им «алгоритмы защиты» (в порядке предпочтения), а также передает некоторые другие параметры (поддерживаемые алгоритмы сжатия данных, 28 байт случайных данных, которое потом будут использованы для генерации общего секрета, идентификатор сессии при желании ее восстановления, в общем про это все будет дальше по тексту). Каждый «алгоритм защиты», вернее cipher suite (если у кого есть идея как перевести на русский в два слова — пожалуйста сообщите, «набор алгоритмов» как-то не звучит), на самом деле идентифицирует три алгоритма:
1) алгоритм обмена ключами, благодаря которому у клиента и сервера после некоторых манипуляций появляются общие 48 байт разделенного секрета, которые позже используются для генерации ключей ко всем остальным алгоритмами (шифрования и MAC)
2) блочный или поточный алгоритм шифрования, используемые для шифрования данных
3) MAC — алгоритм, используемый для подсчета MAC-кода сообщения (идентифицируется хеш-алгоритмом, поскольку в стандарте описан только HMAC).

Получив это сообщение, сервер выбирает набор шифров, который будет использоваться, согласно своей таблице предпочитаемых cipher suites, и отсылает клиенту в сообщении ServerHello. Кроме выбранного набора, сервер также посылает свои сгенерированные случайные данные и идентификатор сессии. Сразу после этого сообщения сервер, в зависимости от выбранного набор алгоритмов, посылает (или не посылает) следующие сообщения: Certificate, ServerKeyExchange, CertificateRequest. В то время как ServerKeyExchange напрямую зависит от выбранного алгоритма обмена ключами, и его содержание нам на данном этапе неинтересно, Certificate & CertificateRequest весьма важны для тех, кто в общих чертах хочет понять как это все работает, но старается избежать излишних подробностей.
В сообщении Certificate сервер посылает свой X.509 сертификат, который удостоверяет аутентичность сервера, а в CertificateRequest — сервер требует от клиента также прислать свой сертификат, чтобы доверить его аутентичность.
Кроме сертификата, сервер также (в пакете ServerKeyExchange) присылает цифровую подпись данных, посылаемых в этом пакете, что позволяет убедиться, что данный пакет действительно прислан сервером, который владеет секретным ключом к присланному сертификату.
Да, тут надо напомнить (или написать), что x.509 сертификат есть привязка некоторого открытого ключа к некоторой сущности (человеку, организации, или, как в данном случае — серверу), которая владеет секретным ключом, соответствующим этому открытому. Сертификаты бывают само-заверенные (self-signed), когда человек сам его подписывает, и заверенные центром сертификации. Основной вопрос, который возникает при встрече с таким сертификатом — доверие к нему, и тут можно полагаться или на свои личные данные (как в случае само-заверенными сертификатами — кто угодно может генерировать такой сертификат), или на доверенные центры, которые налагают свою подпись на сертификат, тем самым как бы доказывая, что они проверили, и этот сертификат действительно соответствует тому-то и тому-то. Более подробно про то, как мы с этим сталкиваемся, будет дальше, а пока-что вернемся к ServerCertificate.
Итак, сервер присылает свой сертификат, и клиент проверяет, действительно ли он доверяет этому сертификату, и в случае отрицательного ответа прерывает сеанс связи. Если сервер потребовал сертификат у клиента, клиент обязан предьявить свой сертификат, иначе связь уже будет прервана сервером. Как правило, последнее используется довольно редко (ну, например в WebMoney), и клиенты аутентифицируются на сервере при помощи логина/пароля.
После получения этого всего клиент посылает свой пакет Certificate (при надобности), ClientKeyExchange, CertificateVerify (цифровая подпись, сгенерированная сертификатом клиента).
Все. После этого, при прошедших взаимных проверках, считается, что клиент и сервер обладают общим секретом, размерностью в 48 байт. Из этого разделенного секрета, при помощи переданных перед этим случайных данных, и некоторых констант, по некоторым правилам (которые я тут конечно не описываю, это чисто технические подробности, а статья уже и так длинная получилась), генерируются ключи для алгоритмов шифрования и проверки MAC-кода (это стоило написать раньше, в общем MAC-код это что-то вроде хеша, но который успешно можно проверить только обладая дополнительно некоторым ключом), и далее идет обмен данным как предусмотрено протоколом уровня приложения.
Для HTTPS — это посылается клиентом запрос, сервером генерируется ответ, и отсылается обратно.

Более наглядно и коротко функционирование протокола можно представить следующей схемой:



Итак, теперь как же и что мы можем увидеть или настроить в процессе использования TLS:
1. Обмен сертификатами. Если сервер присылает сертификат, который не заверен корневым центром сертификации, известным вашему компьютеру (телефону, смартфону, наручным часам, и т.д.), ваше устройство, в зависимости от настроек, но как правило спросит «а доверяете ли вы такому-то сертификату?», на что почти каждый бездумно ответит «да!», перечеркнув всю (ну разве что кроме банального анализа сниферами) безопасность, предлагаемую протоколом TLS. Как например сделано в WebMoney — я был сильно удивлен, когда они предложили мне *свой* рутовый сертификат, который я ничем не мог проверить, кроме ихнего сайта.
2. Сертификат сервера. А как мы собственно узнаем, что сертификат соответствует этому сайту? Узнаем, потому как для TLS сертификатов в поле common name (CN=) прописывается имя сайта, которому он соответствует, которое браузер должен проверять, и в результате несоответствия говорить про ошибку проверки. Отсюда кстати и получаем проблему с тем, что на виртуальном хостинге на одном порту может быть только один HTTPS-сайт: ибо при инициализации соединения сервер должен послать сертификат для нужного хоста (если учесть что сервер это умеет, в апаче настраивается просто один сертификат, насколько я знаю), а нужный хост будет сообщен уже потом, в поле Host: HTTP-запроса.
На данный момент правда есть некоторое расширение TLS протокола Server Name Indication, описанное в RFC 3546 (спасибо IchBinFrei за наводку), однако насколько оно используется и поддерживается сейчас, нужно еще проверить.
Кроме того, сертификат может соответствовать не только одному имени сервера, а нескольким поддоменам, в виде *.host.com

3. Сертификат клиента. Ну, тут все просто — этот сертификат каким-то образом должен быть сохранен на сервер в списке доверяемых, или authority, выписавшая этот сертификат, должна быть доверяемой на сервере.
4. Быстродействие. Кроме того, что инициализация протокола требует трех посылок данных туда и назад (т.е. это уже 3 пинга), еще достаточно времени требует генерирование цифровой подписи (мы рассматриваем сторону сервера), а также разворачивание ключей для симметричных алгоритмов шифрования, что в сумме может занять более полсекунды (кстати, надо заметить, что генерирование DSA-подписи при равном размере с RSA-ключом, происходит раза в 2-4 быстрее). А если на странице при этом подгружается еще и 30 штук картинок, так тут самое время подумать про keep-alive, и про tls session resumption (т.е. продолжение сессии по ее идентификатору, который посылается в ClientHello ). Про это я к сожалению не имею еще данных, как оно на самом деле используется браузерами и серверами, и как будет время, протестирую и напишу.

Вот вроде бы пока что все, если есть вопросы — всегда рад ответить.

+64
17 ноября 2008, 17:49
81
ni4

комментарии (52)

+6
IchBinFrei #
Вроде Server Name Indication (SNI) позволяет настраивать HTTPS для виртуальных хостов
RFC3546
0
SlashDev #
Да, но пока массово это использовать не получится.
IE на XP не умеет этого…
0
khim #
IE7 на XP отлично поддерживает SNI.
0
SlashDev #
Если не секрет, какая сборка IE7 и XP?
0
khim #
Одна из бет его установила :-( В релизе нет — только что проверил на другой машине. Похоже что-то не срослось у них… Грр…

Vista работает нормально…
0
ni4 #
Спасибо, был не в курсе. Однако, надо исследовать насколько это используется ;)
+1
AndyRu #
О SNI пока рано говорить, тк не поддерживается основной массой броузеров. Думаю актуально будет через годик-два.
Сейчас, чтобы работало везде, нужно использовать только разделение по портам/ip-адресам.
0
Caesar #
cipher suite — шифровальный набор?
0
ni4 #
ну тоже как-то… Не очень звучит )
–1
loreley #
когда я писала свой комментарий, этого еще не было, тем не менее, это оптимальный вариант, по-мо, именно что передающий смысл оригинала

согласитесь ведь «алгоритм защиты» — это какая-то отсебятина, в слове cipher нет защиты, это просто шифрование, оно может и не защищать, а вредить.
0
loreley #
лучше бы аргументированно подискутировали со мной на эту тему, вместо того, чтобы просто минусовать, — гораздо интереснее и продуктивнее :)
0
ni4 #
Отчего вы решили что я минусовал )? я не минусовал, я вобще оценки не ставил. Вот могу даже убрать один минус :)
0
loreley #
хех, ну если бы я решила, что минусовали именно вы — я бы все-таки свой комментарий написала ответом непосредственно к вашему комментарию. а в данном случае это было обращение в пространство и вечность к неизвестным тем, кто имеет мнение, отличное от моего, но лишь обозначил его минусом, не потрудившись облечь в слова :)

а топик ваш я изначально заплюсовала — оченно полезная статья для меня лично :)
+4
maniac #
Хорошая вводная.
Кстати у меня сейчас работает несколько name-based виртуальных хостов на одном айпи — у них один сертификат выписанный на домен *.maindomain.com
www.onlamp.com/pub/a/apache/2005/02/17/apacheckbk.html где-то вот так.
+2
pietrovich #
wildcard-сертификат это хорошо, но дорого :)
в принципе все современные броузеры умеют с ними работать, но вот ценовые политики регистраторов относительно wildcard-сертификатов меня расстроили… например thawte. выдержки из их правил:
Wildcard Certificates: [ 2-Year: US$ 1349.00 ] [ 1-Year: US$ 799.00 ] — цена немаленькая, но в моей ситуации это было дешевле чем брать на каждый домен отдельно.

A Wildcard Certificate conveniently allows you to secure multiple sub domains on one domain on the same server using *.domain.com pattern for the common name.

а вот тут и начинаются грабли…
(сходу не нашел, может уже и убрали, но еще 2 года назад когда я этим вопросом занимался у них требовалось получить еще дополнительные «лицензии» на каждый сервер или IP где будет прикручен сертификат. цена была скормнее чем сам сертификат, серверов у нас достаточно для того чтобы цена вышла за рамки разумной :( сейчас колонка *license в прайсах отсутствует, может они уже убрали это идиотское правило, убивающее на корню все попытки сэкономить, но раньше была 100%)

я тогда еще написал в им письмецо, попросил разъяснений. они мне все очень быстренько посчитали за каждый сервер и сказали что «только так и не иначе». в принципе можно было и не покупать эти лицензии, но очень не хотелось нарваться из-за этого на неприятности и получить отзыв сертификата а то и иск…

З.Ы.: брать сертификаты дешевле (goDaddy и ко.) не хотелось
0
pietrovich #
во, нашел переписку…
From: Wener, Lisa <...@thawte.com>

Benefits of thawte's Wildcard Certificate:
* One private key and CSR to manage
* Easy to deploy
* Capable of providing 128bit encryption
* Free site seal
* Highest browser compatibility in the market
* Unlimited free reissues for lifespan of the certificate

Pricing:
* Two year wildcard certificate $1079.21
* Two year wildcard licenses $755.44
* One year wildcard certificate $639.21
* One year wildcard licenses $447.44

(The licenses are used for securing the same domain across multiple
servers — this is used for co-location, clustering and load balancing)


… на дворе было начало 2006 года…
0
pietrovich #
хе-хе… а цены-то выросли!
1349 — 1079.21 = 269.79 = ~25% (269.79/1079.21) за два года o_0
… или это у меня скидка была?!..
0
maniac #
Для целей проекта достаточно было своей маленькой CA, поэтому о цене вопрос не стоял вообще.
0
pietrovich #
хорошо когда можно себе это позволить :)
мы тоже используем для внутренних нужд собственный CA, но когда дело касается паблик-сервисов такой вариант не катит, а все серьезные регистраторы — жадины :(((
+1
nshopik #
>брать сертификаты дешевле (goDaddy и ко.) не хотелось
Чем они вам не угодили тогда? Для себя не вижу разницы т.к. в 2006 году их корневые сертификаты были везде кроме разве что Symbian устройств.
+1
pietrovich #
Для себя не вижу разницы т.к. в 2006 году их корневые сертификаты были везде кроме разве что Symbian устройств.

а вот и не были в 2006…
были проблемы с IE5.5 и IE6 XP SP1(кажется), в общем нем не подошло поскольку в нашей ситуации процент «узнавания» броузерами был далек от заявленных на сайте :(

догда же отказались от comodo и еще нескольких «начинающих» сертификаторов, а из «стариков» Thawte был выбран из-за удобства работы (платежи и все такое)
+1
nshopik #
Молодцы, хотя у нас до сих пор многие банки и крупные компании(билайн для своих дилеров дает самоподписанный) используют самоподписные сертификаты. Особенно удивляют которые работают только в ИЕ, пальцы веером сопли пузырями, но даже на вшивый сертификат от goDaddy сейчас не раскошелились.
0
ni4 #
Мм, на самом деле интересно.
Не могли бы вы написать статейку по поводу практического использования сертификаторов и т.д.? Думаю, достаточно интересно и познавательно получилось бы.
0
pietrovich #
сорри, не могу :(
чукча не писатель, чукча читатель… не умею связно излагать большие объемы данных, особенно в письменной форме. в лучшем случае устно, да и то приходится прибегать к ненормативной лексике чтобы избегать сложных для восприятия/запоминания терминов :")
+1
AnatolyB #
У Google работает куча виртульных хостов на «одном адресе» без всяких SNI, на платформе GAE.
Вся хитрость — в сертификате для "*.appspot.com".
0
ni4 #
ммм, у гугла видел сертификат для www.google.com, или что вы имеете в виду?
0
AnatolyB #
Посмотрите по ссылке:

https://permtrucks.appspot.com
0
ni4 #
Ага, это отдельный сертификат для appspot.
Для www.google.com другой используется.
0
nil #
И изначально извините за возможные ошибки — писал все сходу, и сейчас нет возможности перепроверить, надо бежать.


Если надо бежать, то могли бы проверить позже и запостить без ошибок. Лично мне в статье не понравилось вот что. Предположим я непосвященный читатель (на коих собственно и рассчитана статья). Читаю я все по порядку и вижу:

На втором этапе идет просто обмен данными через установленное логическое соединение, где каждый пакет полезных данных шифруется (если шифрование включено), защищается при помощи MAC, и передается другой стороне через нижележащий протокол (TCP).


Стоп! Что такое «MAC»? Ни расшифровки аббревиатуры, ни пояснения… Читаем дальше:

0
nil #
Упс, прошу прощения, запостилось раньше времени.

Стоп! Что такое «MAC»? Ни расшифровки аббревиатуры, ни пояснения… Читаем дальше:

3) MAC — алгоритм, используемый для подсчета MAC-кода сообщения (идентифицируется хеш-алгоритмом, поскольку в стандарте описан только HMAC).


Что такое «MAC-код сообщения»? Опять ни пояснений, ни расшифровки…

Мой совет, если пишите вводную статью, опишите все детали, чтобы статья была самодостаточной. А то народу после прочтения вашей статьи придется идти куда-нибудь за пояснениями того что вы написали.
0
ni4 #
Будьте терпеливы, дочитайте до конца — «и проверки MAC-кода (это стоило написать раньше, в общем MAC-код это что-то вроде хеша, но который успешно можно проверить только обладая дополнительно некоторым ключем)»
0
ulfurinn #
А что помешало открутить textbox наверх и написать это там, где сразу надо было написать? ;)
+4
pietrovich #
знаете, есть темы которые «непосвященным читателям» лучше совсем не читать… например ядерная физика, некоторые разделы химии, и т.д. поскольку кроме каши в голове оно все равно ничего не даст… нужно иметь некоторые базовые знания прежде чем переходить к более сложным темам. я понимаю что статья не позиционируется как талмуд для гуру, но она и не для чайников.
а исходя из названия ее следует читать начинающим веб-программерам. таким которые уже знают немножко про TCP, понимают чем отличается HTTP от SMTP, но не понимают почему на один порт нельзя повесть два заSSLеных хоста ;)
0
Goganchic #
Статья хорошая, но вот несколько замечаний
1. очень много текста (может быть лучше разбить это на пару статей?)
2. нет иллюстраций (с картинками, откуда и какой hello идет было бы понятнее)
пишите еще :)
0
ni4 #
Ну тут особо ничего не проиллюстрируешь %) посему вот и приходится буквы набирать ;)
0
Goganchic #
>Ну тут особо ничего не проиллюстрируешь %) посему вот и приходится буквы набирать ;)

>нет иллюстраций (с картинками, откуда и какой hello идет было бы понятнее)

вот ведь даже в скобочках написал какую картинку неплохо было бы нарисовать…
0
ni4 #
Таки переборол лень и добавил иллюстрацию.
+1
alexbig #
занятненько…
+1
LDEV #
Интересный экскурс в мир HTTPS. Прочитал на одном дыхании!
0
loreley #
> Каждый «алгоритм защиты», вернее cipher suite (если у кого есть идея как перевести на русский в два слова — пожалуйста сообщите, «набор алгоритмов» как-то не звучит), на самом деле идентифицирует три алгоритма…

cipher suite — шифровальный инструментарий, шифровальный набор, инструментарий (для) шифрования, набор (для) шифрования etc.

0
sk1nny_puppy #
Отличная статья, просто отличная.

Буду очень благодарен если дадите ссылок на материалы по теме, отличные от RFC.
0
ni4 #
Спасибо. К сожалению, всю информацию по этой теме черпал именно из RFC, посему не смогу посоветовать что-то иное, да и не уверен что такое есть. Но если опять таки есть какие-то конкретные вопросы, так пожалуйста, спрашивайте, буду рад помочь.
0
sk1nny_puppy #
Я хочу научиться делать авторизацию по клиентским сертификатам.

Исходные данные: у меня есть некоторая система, в которой TLS используется не только для шифрования трафика, но и для аутентификации клиентов, которые потом авторизуются посредством http запроса.

Так как клиентов достаточно много и авторизуются они достаточно часто, хочется сократить количество запросов к серверу.

Насколько я понял, чисто теоретически это сделать можно — выдаем каждому клиенту свой собственный сертификат и на момент установки соединения (при получении сертификата клиента) мы можем понять, какой именно клиент устанавливает соединение.

Не встречались ли вы с подобной схемой на практике? Если встречались, то насколько она показала себя эффективной?
0
ni4 #
К сожалению, я практически с реальными средствами (Apache и т.д.) такую схему не использовал.
Но вот вроде тут описано то, что нужно: www.garex.net/apache/
0
roller #
cipher suite -> паттерн шифрования?
+1
ni4 #
паттерн какое-то не наше слово ;)
0
loreley #
да, это калька, но оно вполне используется, например, в психологии
0
HnH #
паттерн != шаблон?
+1
Shizik #
Спасибо за статью!
Хочу поделиться отличной ссылкой по тематике: www.inssl.com
0
ni4 #
Какоя-то там страння подача информации. Впрочем, все равно, ссылка наверняка кому-то пригодится )
0
aberezh #
Отлично, кто-то должен был это написать.
0
mrBuG #
А картинка сохранилась только в гуглокэше — и та маленькая :(

Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста.