Как называется число которое вычисляется по специальному алгоритму на основании данных пакета
Перейти к содержимому

Как называется число которое вычисляется по специальному алгоритму на основании данных пакета

  • автор:

Ключи, шифры, сообщения: как работает TLS

SSL и TLS представляют собой развитие одной и той же технологии. Аббревиатура TLS (Transport Layer Security) появилась в качестве замены обозначения SSL (Secure Sockets Layer) после того, как протокол окончательно стал интернет-стандартом. Такая замена вызвана юридическими аспектами, так как спецификация SSL изначально принадлежала компании Netscape. И сейчас нередко названия SSL и TLS продолжают использовать в качестве синонимов, но каноническим именем является TLS, а протоколы семейства SSL давно окончательно устарели и не должны использоваться.

TLS/SSL изначально разработали для защиты коммерческих транзакций, проводимых через Интернет. То есть, основной целью являлось получение относительно безопасного канала для осуществления покупок или управления банковским счётом — хотя, ни первое, ни второе ещё не обрели популярность у рядовых пользователей во времена становления SSL, посколько на дворе была середина 90-х годов XX века. Зато в современном Интернете на TLS/SSL полагаются не только и не столько в деятельности «по продаже товаров», но и при решении гораздо более общей задачи сохранения «приватности» и конфиденциальности важной информации. TLS используется и в современных мессенджерах, и в «мобильных приложениях», что бы под этим термином не подразумевалось. Однако одним из самых распространённых применений TLS остаётся HTTPS. HTTPS стремительно вытесняет незащищённую версию (HTTP) в Интернете: основной объём веб-трафика сейчас передаётся в зашифрованном виде, при этом и так небольшая доля открытого трафика продолжает уменьшаться. В 2023 году уже можно сказать, что почти весь значимый веб-трафик сейчас зашифрован. В новой версии HTTP/2 защита информации средствами TLS должна использоваться по умолчанию.

Благодаря такому положению дел, TLS — один из самых изученных, исследованных протоколов современного Интернета. Вместе с тем, история этого протокола показывает, насколько мало бывает практического толка от исследований. Например, в 2010 году корпорация Microsoft исправила дефект в реализации SSL своего веб-сервера IIS — CVE-2010-3332; а соответствующая уязвимость была продемонстрирована в 2003 году. То есть, семь лет результаты исследования считались чистой теорией, не заслуживающей практического исправления. Впрочем, начиная, примерно, с 2014 года, интерес к поиску уязвимостей в TLS сильно возрос, а обнаруженные уязвимости стали привлекать внимание «самых широких слоёв» интернет-пользователей. Благодаря этому процесс исправления дефектов приобрёл некоторую оперативность и непрерывность.

Впервые SSL внедрили в качестве проприетарной технологии, реализованной в браузере Netscape Navigator, одном из первых веб-браузеров. Версия 1 протокола не была опубликована, а так и осталась внутренней разработкой Netscape, развивавшейся в 1994-95 годах. SSLv2 — следующую, вторую версию протокола — опубликовали, однако спецификация так и не вышла из состояния черновика (draft). Более того, хоть в SSLv2 и скорректировали отдельные дефекты и уязвимости v1, протокол оказался ненадёжным, содержащим серьёзные архитектурные огрехи. SSLv2 очень давно и без оговорок признан небезопасным, поэтому сейчас не должен использоваться. Если постараться, то в Сети всё ещё можно найти архаичные серверы, которые поддерживают SSLv2, поскольку вытеснение дефектных технологий идёт медленно. Однако, если ваш сервер или клиентское ПО всё ещё поддерживает SSLv2, можно смело сказать, что у вас просто нет безопасного канала, вы не поддерживаете TLS вовсе. Более того, на практике было продемонстрировано, что наличие сервера с SSLv2, который использует те же ключи, что и современный TLS-сервер, ставит под угрозу сессии TLS (даже если это разные физические серверы, а трафик к ним доставляется независимо).

SSLv3 — это развитие SSLv2, но с весьма существенными доработками. SSLv3 представлен в 1996 году. Этот протокол получил полноценную спецификацию RFC, но значительно позже своего появления, и в статусе исторического документа: RFC 6101. На время SSLv3 пришлось становление TLS как интернет-технологии. Именно на базе SSLv3 и появился протокол TLS.

Сейчас существует четыре версии TLS, все они описаны в RFC: TLS 1.0, TLS 1.1, TLS 1.2 и вышедшая в 2018 году версия TLS 1.3. TLS 1.0 во многом повторяет SSLv3, за исключением ряда деталей, которые, впрочем, являются весьма важными. (В криптографических протоколах детали важны как ни в каких других протоколах Интернета.) Ключевым отличием TLS от SSL является наличие поддержки целого ряда расширений, позволяющих реализовать современные методы защиты информации. TLS 1.1 и 1.2 достаточно близки к 1.0, но в версии 1.2 появились заметные улучшения, например, используется другая основа псевдослучайной функции и введена поддержка шифров в режиме аутентифицированного шифрования.

Несмотря на то, что номер следующей версии получил лишь прибавку единицы в «младшем разряде», TLS 1.3 весьма и весьма существенно отличается от всех предыдущих версий TLS. В частности, радикально изменена логика установления соединения, а сам протокол стал архитектурно стройнее, благодаря тому, что из спецификации удалены многие сообщения (элементы протокола), а оставшиеся — заметно переработаны. По причине фундаментальных различий версий до 1.3 и 1.3, в данном тексте устаревающие версии TLS 1.0, 1.1, 1.2 рассматриваются, по возможности, отдельно, при этом TLS 1.3 описывается даже более детально, чем предыдущие версии. Есть основания полагать, что в общемировом Интернете TLS 1.3 быстро станет основной версией. Так, протокол версии 1.3 получил RFC в 2018 году, а уже в июле 2019 года поддержку TLS 1.3 для веба реализовали Google, Facebook и Cloudflare, а также основные ветки браузеров Chrome и Firefox, что закрыло основные объёмы веб-трафика. В 2022 году поддержка версии TLS 1.3 стала обычным требованием к более или менее современному веб-сайту. Старые версии TLS остались в «промышленных» и «исторических» приложениях.

Рекомендованными для применения версиями являются TLS 1.3 и 1.2, допускается использование TLS 1.1. Впрочем, в 2021 году вышел RFC 8996, который переводит версии ниже 1.2 в разряд нерекомендуемых. TLS 1.0 повсеместно поддерживается много лет — данный протокол совместим даже с древним браузером IE 6. TLS 1.1 всё ещё представляет ценность, поскольку эта версия поддерживается практически всеми сколь-нибудь распространёнными программными сервисами веба, что важно для разработанных давно, но всё ещё используемых, приложений, которые трудно или даже невозможно обновить. Поддержка TLS 1.2 является повсеместной: все современные браузеры поддерживают эту версию, а проблемы могут возникнуть только с аномально старыми сборками и, иногда, на стороне сервера, при взаимодействии с действительно древними приложениями.

TLS 1.0 можно назвать версией 3.1 SSL. Собственно, именно так и сделано в спецификациях: SSL 3.1 — это TLS 1.0; 3.2 — TLS 1.1; 3.3 — TLS 1.2; 3.4 — TLS 1.3. В шестнадцатеричной записи: 0x0301, 0x0302, 0x0303, 0x0304.

С 2015 года SSLv3, следом за публикацией очередных уязвимостей, перешёл в статус прямо нерекомендуемого. Этот статус вполне официальный, каким только официальным он может быть в рамках технологических традиций Интернета: в июне 2015 года выпущен документ RFC 7568, требующий исключить SSLv3 из разряда поддерживаемых клиентами и серверами протоколов. Остались только версии TLS.

Самая современная версия TLS — 1.3. Активная работа в рамках IETF над новой версией TLS началась в 2014 году. Одной из причин разработки нового стандарта стал резко возросший интерес научно-технического сообщества к архитектуре TLS. Сыграло роль и обнаружение нескольких существенных дефектов в самом протоколе, что гораздо опаснее наличия дефектов в конкретных реализациях. С момента публикации RFC TLS 1.2 прошло почти шесть лет — за это время информационный ландшафт в Интернете успел сильно измениться. RFC TLS 1.3 опубликован в августе 2018 года, этому предшествовало большое количество черновиков (draft). Интересно, что протокол был реализован на практике в нескольких черновых вариантах и поддерживался до публикации RFC, но, так как draft-версии отличались друг от друга в существенных моментах, такая поддержка требовала указания специальной версии протокола (c префиксом 0x7F, например: 0x7F1C — draft-28). Так, в браузере Chrome была реализована версия draft-17. Это же относится и к сервисам, поддерживавшим TLS 1.3 до выхода RFC. Спецификация draft-28 практически не отличалась от финального RFC (собственно, единственное значимое отличие касалось только указываемого номера версии: для RFC-версии нужно указывать 0x0304), поэтому соответствующие библиотеки могли быть быстро переведены на RFC-версию.

Версия TLS 1.3 не только несовместима с предыдущими, но и построена на другой инженерной идеологии. Различие обусловлено переосмыслением модели угроз, в рамках которой проектируется новый протокол: TLS попытались сделать и более быстрым (по крайней мере, потенциально), и более защищённым, и более скрытным. Что касается последнего аспекта, то речь идёт о совершенно новом для TLS направлении: сведении к минимуму утечек так называемой метаинформации, то есть, данных о том, какие сообщения передаются внутри сессии, в каком состоянии сессия находится в данный момент времени. Существенные усилия были направлены на то, чтобы даже хорошо оснащённая третья сторона не могла узнать ничего более, кроме как о факте установления TLS-соединения.

Предназначение TLS

TLS ставит своей целью создание между двумя узлами сети защищённого от прослушивания и подмены информации канала связи, пригодного для передачи произвольных данных в обоих направлениях, а также проверку того, что обмен данными происходит между именно теми узлами, для которых канал и планировался. Эти задачи называются, соответственно, обеспечением конфиденциальности, целостности и подлинности соединения (аутентификации). Из фундаментальных задач защиты информации, TLS не охватывает только одну: обеспечение доступности информации — и эта задача находится далеко за рамками данного протокола.

Предполагается, что TLS работает поверх существующего между узлами «потокового» соединения (с которым обычно связан «сокет» — откуда старое название SSL, Secure Sockets Layer). Сейчас, в большинстве случаев, TLS будет работать поверх TCP. Именно TCP отвечает за установление соединения, разбивку данных на пакеты, гарантированную доставку этих пакетов (при наличии соединения, естественно) и за разные другие телекоммуникационные моменты. TLS предполагает, что между узлами установлено надёжное соединение, поэтому, например, протокол не охватывает повторную отправку потерянных пакетов данных. (Для работы в условиях негарантированной доставки и неустойчивой связи существует особый, родственный протокол — DTLS, который мы здесь не рассматриваем.) TLS использует установленный канал связи для передачи TLS-сообщений, одного из базовых «строительных блоков» протокола. Эти сообщения кардинальным образом отличаются от пакетов данных (IP-пакетов в TCP/IP) и представляют собой структуру более высокого уровня. TCP позволяет надёжно обмениваться данными, но содержимое пакетов (за исключением специальных случаев) может быть легко прочитано кем-то, кто имеет доступ к каналу связи. Хуже того, этот кто-то может заменить пакеты или изменить передаваемые в них данные. Именно для защиты от этих угроз и используется TLS.

Другими словами, модель угроз TLS предполагает, что атакующий может как угодно вмешиваться в канал связи, в том числе активно подменять пакеты и вообще — прерывать связь. Ключевые задачи TLS: 1) обеспечить конфиденциальность, то есть реализовать защиту от утечек передаваемой информации; 2) обеспечить обнаружение подмены, то есть реализовать сохранение целостности передаваемой информации; 3) обеспечить аутентификацию узлов, то есть дать механизм проверки подлинности источника сообщений. Кроме того, в TLS 1.3 существенное внимание уделено задаче сокрытия метаинформации (это подзадача из первого пункта, обеспечения конфиденциальности), под метаинформацией понимается совокупность таких сведений о TLS-соединении, которые позволяют косвенно судить о передаваемых в защищённом режиме данных. Например, к метаинформации относятся сведения об открытых криптографических ключах узлов, о времени соединения, об адресах, именах узлов и так далее.

TLS как-то справляется с описанными только что задачами, но не следует полагать, что TLS решает их полностью. Такое мнение является большой ошибкой, к сожалению, весьма распространённой. Доказательством того, что TLS не решает данные задачи полностью, являются уязвимости, обнаруженные в самом протоколе (а не только в его реализациях). Протокол и его реализации пытаются решить описанные задачи на максимально доступном уровне надёжности. Однако TLS в целом не обладает доказанной стойкостью, как не обладают ей и многие важнейшие составляющие части протокола. Обычно в качестве экстремального примера данного наблюдения приводят такую рекомендацию: не следует доверять TLS и связанным технологиям свою жизнь или жизнь других людей.

TLS использует концепцию «клиент-сервер», которая, в логике данного протокола, во многом совпадает с логикой «клиент-сервер» TCP: например, и там, и там соединение инициирует клиент.

Логика TLS

TLS работает с записями (records). Записи находятся в фундаменте протокола. Это нижний транспортный уровень TLS. Сообщения TLS, относящиеся к верхним уровням, могут быть разбиты на несколько записей. Это достаточно важный момент: в некоторых случаях TLS-сообщения требуют сборки из нескольких записей, что существенно влияет на логику обработки состояний протокола.

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

В TLS, за некоторыми исключениями, используется формат, в котором представление структуры данных начинается с заголовка, обозначающего тип данных и их длину. Части этого заголовка, определяющие структуру, всегда определены строго: то есть, определено количество байтов, выделенных для записи типа, перечислены все допустимые значения этих байтов и способ их интерпретации; определено количество байтов для записи длины полезной нагрузки, способ интерпретации записи. Так, сообщения, внутри которых невозможно отказаться от полей переменной длины, начинаются с заголовка, содержащего запись с количеством байтов, составляющих сообщение. При этом в определённых спецификацией случаях запись типа может быть пустой (то есть, тип не указывается вовсе, байты для его записи не резервируются). Для некоторых блоков данных может не указываться длина, но это всегда означает, что полезные данные имеют строго зафиксированную спецификацией длину в байтах — например, два байта для обозначения версии (см. ниже). Такой подход, который немного напоминает префиксные коды, позволяет избежать многих проблем при обработке данных. Так, сразу исключается целый класс «инъекций», основанный на дополнении пакетов. Естественно, изменить запись, добавив что-то в конец — возможно, но придётся скорректировать и значение длины пакета, которое обрабатывается раньше полезной нагрузки. В целом, строгое определение полей при помощи заголовков фиксированного формата — это именно тот способ задания структур данных, который нужно использовать в протоколах безопасности.

Разберём заголовок TLS-записи. Заголовок имеет длину 5 байтов, и следующий формат:

00 Тип (1 байт) 01 Версия протокола (2 байта) 03 Длина данных (2 байта)

Тип — это тип записи (фактически, тип определяет то, как будет интерпретироваться содержимое записи). Определено четыре типа: 20 (0x14) — сообщение Change Cipher Spec (CCS), в версии 1.3 данное сообщение передаётся только как «фиктивное», не имеет логической роли в самом протоколе, но может повлиять на процесс обработки соединения в конкретной реализации TLS; в более ранних версиях — CCS играет важную роль, обозначая момент перехода к защищённому обмену сообщениями; 21 (0x15) — сообщение Alert (это не обязательно предупреждение, есть вполне «фатальные alert-ы»); 22 (0x16) — сообщение Handshake (начало установления соединения); 23 (0x17) — Application Data (запись содержит данные приложения — то есть, полезную нагрузку); трактовка типа Application Data существенно различается в версии 1.3 и предыдущих версиях.

При передаче информации основные преобразования с шифрами и кодами аутентификации как раз происходят в блоке данных записи с типом 23 (0x17) Application Data. В TLS 1.3 зашифрование информации узлами начинается существенно раньше, чем в более ранних версиях: зашифрованы уже сообщения Handshake (тип 0x16). До версии 1.3 — записи, отличные от Application Data, обычно передаются в открытом виде, но, тем не менее, тоже могут быть зашифрованы, в зависимости от текущего состояния TLS-соединения.

Версия протокола — это номер версии, записанный в двух байтах, как указано выше: 03 00 — это SSLv3, 03 01 — TLS 1.0; 03 02 — TLS 1.1; 03 03 — TLS 1.2; TLS 1.3 в этом поле предписывает использовать значение 03 03, то есть, фиктивную версию 1.2, само поле при этом игнорируется.

Длина данных — количество байтов, содержащих данные (сами байты данных следуют после заголовка). Так как используется сетевой порядок байтов, для определения длины нужно значение первого слева байта (h) умножить на 2 8 и прибавить значение второго (младшего, l) байта, вот так: h * 256 + l. Пустой блок данных (длина нуль) допускается протоколом, но иногда вызывает сбои в клиентах, написанных с ошибками. Максимальная допустимая длина данных записи в TLS 1.3 — 2 14 байтов.

Пример заголовка записи TLS 1.1 (значения байтов — в шестнадцатеричной записи):

16 03 02 03 FE

Раскодируем: это сообщение Handshake (0x16); версия 3.2 (0x03,0x02)- то есть TLS 1.1; длина данных — 0x03FE байтов (1022 байта).

Заголовок всегда передаётся в открытом виде. В том числе, при использовании TLS 1.3. Однако в TLS 1.3 предусмотрено сокрытие реального типа записи (для защищённых записей) — подробнее этот момент разобран в отдельном подразделе.

За заголовком должно следовать определённое число байтов (>=0), которые представляют собой содержимое данной записи. Максимальное значение в версиях до 1.3 — 18432 байта. 18432 = 16384 + 2048. То есть, 16 килобайт + два раза по килобайту. Такое значение может показаться странным. Действительно, «базовая» версия записи, описанная в спецификации, предполагает блок данных в 2 14 байтов, то есть 16 килобайт. Но такой размер относится только к записям, содержащим открытый текст (TLSPlaintext). Например, к сообщениям, управляющим установлением соединения (Handshake). Здесь, действительно, максимальная длина — 16К.

Для защищённых записей ситуация меняется. Во-первых, в TLS до версии 1.3 было возможно использование сжатия данных. Под «сжатием» здесь имеется в виду использование кодирования, минимизирующего количество битов, необходимых для записи данных — тот же процесс, который многим знаком по программам-архиваторам. Собственно, спецификация TLS предписывала, что сжиматься должны все данные защищённой записи. Но на практике это довольно давно означает не совсем то, о чём можно подумать (это нередкая для TLS ситуация): на практике, сжатие не используется (или, если хотите, используется только «тривиальное сжатие»). Дело в том, что TLS всех версий среди перечня алгоритмов сжатия содержит алгоритм null, означающий, что никакого сжатия в реальности не производится, а данные кодируются «как есть». Этот алгоритм служит вариантом по умолчанию (раньше можно было встретить алгоритм DEFLATE, но он давно относится к нерекомендованным из-за обнаруженных уязвимостей). Тем не менее, реально сжатые данные могут, в ряде случаев, оказаться длиннее, из-за особенностей алгоритма сжатия (это выглядит контринтуитивным, но для любого практического алгоритма сжатия можно подобрать входные данные таким образом, что результат кодирования «со сжатием» окажется длиннее исходных данных). TLS отводит на такое увеличение длины 1024 байта (хорошо реализованные алгоритмы используют значительно меньше). В TLS 1.3 сжатие прямо запрещено спецификацией, поэтому данное «дополнение» не используется.

Во-вторых, для проверки целостности зашифрованных данных к ним приписывается код аутентификации сообщения (MAC — значение, позволяющее проверить, что сообщение не было изменено; эти коды подробно описаны ниже) и дополнительная информация (вроде векторов инициализации шифров) — на это в TLS старых версий отводится ещё 1024 байта. Итого — 2048, хотя данный момент и вносит некоторую сумятицу в организацию протокола. Естественно, универсальные — и, потому, фиксированные, — 16K в качестве максимального предела смотрелись бы лучше. В реальности, редкая запись TLS дотягивает и до 16K — обычно длина заметно меньше.

В TLS 1.3 ситуацию упростили: для защищённых данных дополнительно допускается только 256 байтов для кода аутентификации, сжатие запрещено. То есть, максимальный размер: 16384 + 256 = 16640. При этом в 16384 байта входят байты дополнения (record padding) — байты со значением 0, которые могут приписываться в конец блока защищаемых данных для того, чтобы скрыть их длину, а также для выравнивания размера записи.

Код аутентификации сообщения — важнейший элемент защиты информации в TLS. В версиях до 1.3 обычно используется HMAC — алгоритм вычисления кода аутентификации, базирующийся на той или иной хеш-функции; типичный выбор: SHA-1 или SHA-256. Код аутентификации приписывается к блоку данных. Один из архитектурных дефектов версий TLS до 1.3 состоит в том, что соответствующие спецификации предписывают сперва вычислять MAC, а потом зашифровывать сообщение. То есть, вычисленный код аутентификации присоединяется к открытому тексту сообщения, а потом всё вместе зашифровывается. При этом принимающая сторона должна сперва расшифровать полученные данные, а потом проверить MAC. Такой метод легко приводит к возникновению «криптографических оракулов», на использовании которых основано несколько эффективных атак против TLS (эти атаки подробно рассмотрены в специальном разделе). Современный подход: код аутентификации добавляется после зашифрования открытого текста, то есть MAC вычисляется для уже зашифрованного сообщения и прикрепляется к нему («сперва шифр, потом — MAC»). Для внедрения современного подхода в спецификации добавлено специальное расширение, позволяющее клиенту и серверу договориться о том, в какой последовательности они генерируют коды аутентификации — RFC 7366. Современная версия TLS 1.3 использует шифры только в режиме аутентифицированного шифрования (а именно — AEAD). Этот режим не нуждается в отдельном MAC, так как целостность данных гарантирует сам алгоритм зашифрования (подробное описание дано ниже, в разделе, посвящённом шифрам). Пример: AES в режиме GCM, этот вариант является предпочтительным, поддерживается всем современным ПО, и имеет большое распространение.

  • криптосистема, используемая для аутентификации (аутентифицируются сервер и сеансовый секрет);
  • шифр, который послужит для защиты передаваемых данных в симметричном режиме;
  • хеш-функция, являющаяся основой для HMAC.

Шифронаборы имеют важнейшее значение для безопасности TLS. Выбор нестойкой комбинации означает, что достаточной защиты конкретная реализация TLS не обеспечивает. Поэтому, в TLS 1.3 число допустимых шифронаборов резко сокращено — рекомендовано только четыре (2019). Применительно к вебу: браузеры используют встроенный комплект шифронаборов, обычно это 10-15 вариантов, которые могут использоваться с разными версиями TLS; на сервере поддерживаемые шифронаборы настраиваются администратором сервера. Реестр IANA в настоящий момент содержит свыше 300 (трёх сотен, да) шифронаборов (в число которых входят и так называемые псевдошифры, которые используются в качестве сигналов). Среди шифронаборов встречается экзотика вроде TLS_KRB5_WITH_RC4_128_SHA и безнадёжно устаревшие варианты, например — TLS_RSA_EXPORT_WITH_RC4_40_MD5. Современные серверы и клиенты не должны использовать подобного. Наличие того или иного шифронабора в реестре IANA означает, что этому шифронабору присвоен индекс (номер) и обозначение, не более того: нужно понимать, что данный реестр не имеет никакого отношения к тому, какие шифры и криптосистемы рекомендованы или не рекомендованы для использования. Добротным вариантом считается, как минимум, TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA256, допустимый для TLS 1.2: то есть, генерация общего секрета проводится по протоколу Диффи-Хеллмана на эллиптических кривых, для аутентификации данных и параметров на этапе установления соединения используется криптосистема электронной подписи ECDSA (тоже работающая на эллиптических кривых), полезная нагрузка зашифровывается AES с 256-битным ключом в режиме GCM, а в качестве хеш-функции служит SHA-256 (здесь используется при генерации сеансовых ключей).

Первоначальное соединение (Handshake)

(TLS Handshake иногда в современных русскоязычных статьях называют «рукопожатием», что является прямым, и не очень удачным, переводом английского термина; этот вариант мы не станем использовать.)

Клиент и сервер должны договориться об используемых шифрах и методах аутентификации, согласовать ключи и другие параметры сеанса связи. Набор согласованных параметров называется криптографическим контекстом. Согласование происходит при установлении соединения, путём обмена специальными сообщениями — handshake-сообщениями. Такой обмен в TLS осуществляется поверх обмена записями. Каждое Handshake-сообщение содержит специальный заголовок, состоящий из четырёх байтов. Первый байт обозначает код типа сообщения, три следующих байта — длину сообщения.

В TLS 1.3 установление соединения организовано таким образом, что уже на втором шаге используется защищённый режим, то есть, разбор Handshake версии 1.3 требует, как минимум, использования протокола Диффи-Хеллмана и симметричных шифров. К TLS 1.2 и раньше — этот момент не относится. Поэтому мы сначала подробно разберём установление соединения в 1.2, потом рассмотрим протокол Диффи-Хеллмана (применительно к TLS) и симметричные шифры, после этого перейдём к анализу Handshake версии 1.3. (Заметьте, что для понимания принципов построения TLS 1.3 — необходимо понимание версии 1.2, особенно с учётом того, что 1.3 отличается весьма существенно.)

Сообщения Handshake TLS 1.2 (и ранее)

Handshake-сообщения отправляются в виде TLS-записей, которые мы обсудили выше. Это означает, что заголовку сообщения предшествует заголовок записи, где тип сообщения определён кодом 22 (0x16) — см. выше. Несколько Handshake-сообщений могут быть переданы в одной записи — это распространённый случай, например, так нередко поступает Miscrosoft IIS. А самое интересное, что одно сообщение может быть разбито на несколько записей, передаваемых последовательно — спецификация допускает и это, например, можно «нарезать» сообщения на записи длиной в один байт полезной нагрузки каждое. К счастью, последний вариант скорее теоретический, на практике встречается исчезающе редко. (А экстремальный метод «запутывания» состоит в передаче перед разрезанным на несколько записей сообщением пустых записей, то есть TLS-записей, состоящих из одного заголовка, где в качестве длины указан нуль; такой вариант также допускается спецификацией.) Все эти случаи должны корректно поддерживаться добротной реализацией TLS. Таким образом, находящийся ниже протокола установления соединения уровень TLS-записей нужно рассматривать как некий потоковый псевдосокет, куда сообщения записываются как есть, и где они могут быть разрезаны на блоки для передачи. Единственное, что запрещает спецификация TLS — это нарушение порядка при доставке записей. Всё это верно и для TLS 1.3.

Спецификация предполагает, что любой клиент и сервер TLS по умолчанию уже согласовали шифронабор null, без MAC и с «нулевым» сжатием. То есть клиент и сервер могут обмениваться сообщениями в виде открытого текста без аутентификации. Установление соединения всегда начинает клиент. В типичной конфигурации, TLS здесь оказывается схож с TCP, так как, например, при работе с сервером по HTTPS — TCP-соединение также инициирует клиент. Благодаря историческому совпадению принципов построения технологий, клиент HTTPS, TLS, TCP — один и тот же узел. Можно предложить конфигурации протоколов, когда это не так, но в наиболее распространённой ситуации веба — подобные конфигурации едва ли возможны.

Client Server ClientHello --------> ServerHello Certificate* ServerKeyExchange* CertificateRequest* [ChangeCipherSpec] Application Data Схема обмена Handshake-сообщениями TLS 1.2 (ChangeCipherSpec - не является сообщением Handshake). Источник: RFC 5246

Первым сообщением в протоколе установления TLS-соединения всегда является сообщение ClientHello (тип 01). Сообщение содержит следующие данные:

  1. версия протокола — максимальная версия, которую готов поддерживать клиент (обратите ещё раз внимание — речь в этом разделе идёт о протоколе версии 1.2 или более ранней);
  2. 32 байта случайных значений — ClientRandom. Изначально, в спецификации рекомендовалось использовать первые 4 байта для передачи UNIX-таймстемпа, а оставшиеся 28 — заполнять результатом работы криптографического генератора псевдослучайных чисел. Однако сейчас многие браузеры и веб-серверы генерируют все 32-байта случайным образом. Забегая чуть вперёд: предполагалось, что наличие таймстемпа в handshake-сообщениях может помочь при обнаружении проблем с подменой времени на том или ином узле. Однако данный метод сейчас никак не используется, поэтому часто все байты ClientRandom случайны. Такой подход закреплён и в TLS 1.3;
  3. идентификатор TLS-сессии — SessionID: TLS позволяет возобновлять ранее установленные сессии, используя сокращённый вариант протокола установления соединения. Идентификатор сессии как раз содержит номер такой сессии, параметры которой (возможно) сохранены на сервере (подробнее мы рассмотрим этот вариант ниже). В TLS 1.3 данное поле может быть пустым, а если присутствует, то играет другую роль: обнаружив в ClientHello поле SessionID, сервер включает его значение в свой ответ без изменений, при этом как номер сессии SessionID в 1.3 не используется, но может служить инструментом имитации сессий версии 1.2;
  4. список шифронаборов, которые поддерживает клиент — Cipher Suites. Порядок шифронаборов в списке отражает их степень предпочтения клиентом (предпочтительные передаются первыми слева), этот порядок — всего лишь рекомендация, и сервер далеко не всегда ей следует;
  5. список поддерживаемых методов сжатия — Compression Methods, порядок, опять же, соответствует степени предпочтения, но обычно в этом поле лишь одно значение — null, так как сжатие не рекомендуется использовать. В TLS 1.3 — сжатие прямо запрещено, но, по «историческим причинам», данное поле сохраняется, с фиксированным значением null;
  6. данные, определяющие параметры различных расширений протокола установления соединения (расширения ClentHello).

Каждое из полей в сообщении ClientHello имеет свой формат, а полю предшествуют данные о его длине и, в случае расширений, дополнительный заголовок. Заголовок обычно содержит тип расширения и длину его данных. Такая структура позволяет реализациям корректно разбирать сообщения. Например, список шифронаборов может быть представлен в следующем виде (шестнадцатеричная запись):

[. ] 00 06 c0 2b c0 2f с0 29 00 06 - шесть байтов занимают идентификаторы шифронаборов; c0 2b - шифронабор 0xc02b - TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256; с0 2f - шифронабор 0xc02f - TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256; с0 29 - шифронабор 0xc029 - TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256.

Расширения ClientHello позволяют использовать различные нововведения, которые появились позже, чем структура данного сообщения. Так, например, в расширениях могут быть перечислены эллиптические кривые, которые готов использовать клиент. Самым распространённым расширением является SNI (Server Name Indication), позволяющее браузеру (или другому TLS-клиенту) указать имя веб-сервера, с которым он пытается установить соединение. SNI необходимо, например, для того, чтобы на одном IP-адресе могли корректно откликаться по HTTPS веб-серверы, размещённые под разными именами (доменами).

Разберём ClientHello в деталях. В качестве примера возьмём специальный образец ClientHello, сгенерированный утилитой опроса TLS-серверов в исследовательских целях. В качестве сервера используется sbrf.ru.

Смещение Байты Комментарий (десятичное) (шестнадцатеричное представление) 0000 16 ; Первый байт заголовка TLS-записи - тип 22, сообщение Handshake. 0001 03 02 00 65 ; Версия TLS 1.1 (03 02), длина пакета данных - 0065 (101 байт). 0005 01 ; Первый байт сообщения TLS: 01 - тип ClientHello. 0006 00 00 61 ; Длина блока данных - 000061 (97 байтов). 0009 03 02 ; Версия TLS 1.1 (03 02) клиента. 0011 53 53 4c 20 53 ; 32 байта случайных значений, ClientRandom [. ] 0043 00 ; Длина поля SessionID - 0 байтов, так как SessionID в данном сообщении не используется (в случае браузерного ClientHello будет указана длина записи SessionID, за которой последует значение SessionID). 0044 00 16 ; Длина поля со списком шифронаборов (Cipher Suites) - 22 байта: в данном ClientHello указано 11 шифронаборов, по два байта на каждый из них. 0046 c0 2b ; Шифронаборы. [. ] 0068 01 00 ; Длина поля CompressionMethods (1 байт) и значение этого поля (00 - null, без сжатия: клиент не поддерживает сжатие). 0070 00 22 ; Длина поля Extensions (0022 - 34 байта), поле, в нашем случае, содержит расширения: SNI, Elliptic Curves, Elliptic Curves Point Formats. 0072 00 00 ; Расширение SNI (Server Name Indication, тип 0000). Данное расширение позволяет указать имя сервера, с которым будет происходить соединение по протоколу HTTPS (в данном случае - HTTPS, но SNI может использоваться и для других протоколов). 0073 00 0c ; Длина данных в расширении SNI. 0075 00 0a 00 00 07 ; Заголовок расширения SNI - длина списка имён (000a - 10 байтов), тип имени (hostname - 00), длина строки с именем (7 байтов). 0080 73 62 72 66 2e 72 75 ; Значение имени SNI: sbrf.ru 0086 00 0a ; Тип расширения - Elliptic Curves (000a), данное расширение позволяет клиенту указать список эллиптических кривых, с которыми этот клиент умеет работать. 0088 00 08 ; Длина данных расширения (8 байтов). 0090 00 06 ; Длина списка кривых (6 байтов - три кривые, по два байта на идентификатор). 0092 00 17 00 18 00 19 ; Идентификаторы кривых. 0098 00 0b 00 02 01 00 ; Расширение Elliptic Curves Point Format, тип (000b), длина (0002), длина списка (01), формат записи точек - полный (то есть, полностью передаются две координаты x,y в аффинном представлении; есть форматы со сжатием, где передаётся только одна координата, х, а для второй указывается знак).

Согласно спецификации, после отправки ClientHello, клиент ожидает ответа сервера. В ответ может прийти либо сообщение об ошибке, в виде Alert, либо сообщение ServerHello.

Alert — короткие сообщения, содержащие информацию об уровне ошибки и о её типе. Сообщение Alert, например, может сигнализировать о сбое установления соединения. Рассмотрим такой вариант подробнее:

Смещение Байты Комментарий (десятичное) (шестнадцатеричное представление) 0000 15 ; Тип сообщения - 0x15 - Alert. 0001 03 01 ; Версия протокола - 0x0301 - TLS 1.0. 0003 00 02 ; Длина сообщения (два байта). 0005 02 ; Уровень ошибки - 0x02 - Fatal (фатальная, соединение невозможно). 0006 28 ; Состав ошибки - 0x28 - Handshake Failure (сбой установления соединения).

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

  1. версию протокола, которую будут использовать клиент и сервер;
  2. 32 байта случайных значений — ServerRandom. С этой строкой ситуация такая же, как и с Client Random: первые четыре байта могут быть таймстемпом, а могут и не быть. Интересным свойством данной метки времени является то, что она может послужить некоторым справочным материалом при последующем анализе записанного трафика: если сервер отвечает достоверным значением времени, то, учитывая, что полный набор сообщений Handshake содержит сообщение, криптографически удостоверяющее целостность данных (см. ниже про сообщение Finished), получаем подписанную сервером квитанцию о времени соединения по его часам, с точностью до секунды — иногда эти данные помогают правильно составить запрос в адрес администрации сервера об извлечении записей из логов;
  3. идентификатор сессии — SessionID, присвоенный новой сессии сервером (в случае TLS 1.3 — данное поле обязательно повторяет SessionID клиента);
  4. выбранный сервером шифронабор — Cipher Suite, этот шифронабор будет использоваться в дальнейшем и клиентом, и сервером. Сервер выбирает шифронабор из предложенных клиентом в ClientHello, но не обязательно следует приоритету клиента: распространена как раз обратная ситуация, когда сервер исключительно сам определяет предпочтительный шифронабор;
  5. выбранный сервером метод сжатия — скорее всего, это null;
  6. некоторый набор расширений.

В современных реализациях TLS раздел «Расширения» (Extensions) имеет очень большое значение, так как в нём передаются параметры, определяющие схему работы TLS-соединения. Предназначение ServerHello — согласовать параметры этого соединения. TLS здесь использует хорошо известную схему «запрос-ответ-подтверждение» (за исключением варианта ускоренного установления соединения), а сообщения ClientHello и ServerHello представляют собой, соответственно, запрос и ответ. Эти сообщения не содержат никакой секретной информации и передаются в открытом виде (но в TLS 1.3 ситуация поменялась — практически сразу же сообщения Handshake передаются в зашифрованном виде, тем не менее, ServerHello и ряд расширений всё равно открыты). Данные сообщения, особенно — ClientHello, повсеместно используются в системах DPI для обнаружения факта установления (или попытки установления) TLS-соединения.

В рамках каждой сессии TLS клиент и сервер согласовывают следующие параметры (RFC 5246):

  1. роли узлов: какой узел является клиентом, а какой — сервером. Распределение этих ролей происходит «естественным образом», при установлении соединения — клиент всегда начинает сессию;
  2. алгоритм PRF (псевдослучайная функция, PseudoRandom Function) — используется для вычисления сеансового ключа на основе данных, переданных в ClientHello и ServerHello; клиент и сервер должны использовать согласованный алгоритм PRF;
  3. шифр — данные в TLS зашифровываются симметричным алгоритмом; для успешного зашифрования потока данных внутри сессии оба узла должны использовать один и тот же алгоритм, в согласованном режиме. Узлы согласуют тип шифра (потоковый, блочный), сам шифр, режим использования шифра, размер ключа, размер блока (для блочных шифров), инициализирующие векторы, а также дополнительные параметры (если они требуются, например, в случае с AEAD-режимами);
  4. алгоритм вычисления кода аутентификации сообщения (MAC) — в рамках сессии необходимо использовать согласованный алгоритм аутентификации. Для AEAD-режимов отдельно MAC не используется (поскольку реализуется алгоритмом AEAD);
  5. алгоритм сжатия — также должен быть общим, однако сжатие, фактически, не используется, что означает общий алгоритм null;
  6. основной секрет (MasterSecret) — массив из 48 секретных байтов, известный серверу и клиенту. Основное предназначение данного массива — определение сеансового ключа. 384-битное значение MasterSecret позволяет вычислить секретные ключи сессии. Если это значение стало известно третьей стороне, то она сможет расшифровать трафик сессии. В TLS 1.3 используется более сложная схема, состоящая из секретов разных уровней, которые соответствуют стадиям работы протокола;
  7. случайные данные клиента (ClientRandom) — 32 байта случайных значений, передаются в ClientHello;
  8. случайные данные сервера (ServerRandom) — 32 байта случайных значений, передаются в ServerHello.

Эти параметры позволяют построить контекст для работы криптосистем, которые будут обрабатывать защищённые TLS-записи на стороне сервера и клиента. Помимо ClientHello и ServerHello в ходе установления соединения узлы обмениваются несколькими другими сообщениями.

Со стороны сервера это следующие сообщения (конкретный состав и содержание — зависят от выбранного сервером режима работы).

Certificate. Ключевым аспектом для современных реализаций TLS является использование TLS-сертификатов (ранее они назывались SSL-сертификатами, сейчас рекомендуется вариант с TLS), мы рассмотрим их подробнее ниже. Сертификаты передаются сервером в сообщении Certificate. Это сообщение присутствует практически всегда. Серверный сертификат содержит открытый ключ сервера. В теории, спецификация позволяет установить соединение без отправки серверных сертификатов. Это так называемый «анонимный» режим, однако он практически не используется, как и режимы TLS без шифров. Так, свыше 99% веб-серверов, поддерживающих TLS, передают TLS-сертификаты. В типичной конфигурации сообщение Certificate будет включать несколько TLS-сертификатов, среди которых один серверный сертификат и так называемые «промежуточные сертификаты», позволяющие клиенту выстроить цепочку валидации. Серверный сертификат — это сертификат, который по имени соответствует серверу и содержит серверный открытый ключ электронной подписи (в большинстве случаев — RSA или ECDSA). Спецификация предписывает строгий порядок следования сертификатов в сообщении: первым должен идти серверный сертификат, а последующие — в порядке удостоверения предыдущего. Однако на практике серверы нередко отправляют сертификаты в произвольном порядке. На клиентской стороне браузеры тоже достаточно свободно относятся к порядку сертификатов, пытаясь выстроить из них корректную цепочку, применяя различные перестановки. Такое положение дел прямо нарушает спецификацию TLS версий 1.0, 1.1, 1.2, но такова реальность: игнорируя криптографические строгости — реализации допускают вольности (последние нередко ведут к уязвимостям). Хотя, достаточно сложно найти веские причины для строго порядка следования сертификатов. В TLS 1.3 данное требование смягчили, сделав допустимым произвольный порядок промежуточных сертификатов (серверный всё равно ожидается первым).

ServerKeyExchange. Сообщение, содержащее серверную часть данных, необходимых для вычисления общего сеансового ключа. Сообщение может отсутствовать, а в TLS 1.3 оно не используется, так как новая схема Handshake для обмена криптографическими параметрами основана на расширениях Hello-сообщений. В версии TLS 1.2 и ранее ServerKeyExchange обычно содержит параметры протокола Диффи-Хеллмана (DH), однако исторический вариант предусматривает и передачу временного ключа RSA. Если используется классический вариант DH, то в сообщении ServerKeyExchange передаётся значение модуля (простое число) и серверный открытый ключ. В варианте на эллиптических кривых (ECDH) — идентификатор самой кривой и, аналогично DH, открытый ключ сервера. Параметры подписываются сервером (за исключением экзотических вариантов обмена, вроде анонимного DH), клиент может проверить подпись при помощи открытого ключа сервера из TLS-сертификата. Этот шаг позволяет клиенту убедиться, что параметры получены именно от того сервера, который имеет доступ к секретному ключу от серверного сертификата. В зависимости от используемой криптосистемы, подпись может быть RSA или ECDSA, другие варианты — редки. Подпись на параметрах DH очень важна, так как позволяет защитить соединение от атаки типа «человек посередине». В разных версиях TLS подпись вычисляется для разных наборов данных. В TLS 1.0, 1.1 (при использовании RSA, что является основным вариантом) — от объединения значений двух хеш-функций — MD5 и SHA-1, взятых от параметров обмена DH. В TLS 1.2 — от значения хеш-функции, заданной в используемом шифронаборе, вычисленного для объединения ServerRandom, ClientRandom и параметров обмена DH (ECDH). В современной (2023) ситуации сообщение ServerKeyExchange можно увидеть в большинстве TLS-сессий (для версий, отличных от 1.3).

CertificateRequest. В TLS возможна обоюдная (двухсторонняя) аутентификация узлов, использующая TLS-сертификаты. Сертификаты могут быть выпущены для самых разных имён и, соответственно, они пригодны для аутентификации клиента. Обычно, клиентские сертификаты используются при доступе к банковским, платёжным системам, к корпоративным веб-шлюзам различного назначения, а также к государственным информационным системам через веб-интерфейс. Сервер может запросить клиентский сертификат при помощи сообщения CertificateRequest. Сообщение содержит список поддерживаемых сервером типов сертификатов и типов криптосистем — здесь указываются криптосистемы, относящиеся к процедуре валидации клиентского сертификата: алгоритмы подписи, хеш-функции. Также в составе CertificateRequest могут быть переданы имена удостоверяющих центров, ключи которых сервер будет использовать для проверки клиентского сертификата.

ServerHelloDone. В TLS 1.2 и раньше — это сообщение сигнализирует об окончании набора сообщений, возглавляемого ServerHello. Сообщение имеет нулевую длину (в TLS-записи ServerHelloDone соответствует 4 байта, так как присутствует заголовок записи) и служит простым флагом, обозначающим, что сервер передал свою часть начальных данных и теперь ожидает ответа от клиента.

Итак, сервер отвечает на ClientHello последовательностью сообщений TLS Handshake, максимум — пятью сообщениями. Типичный для TLS 1.2 случай: передача сервером четырёх сообщений — ServerHello, Certificate, ServerKeyExchange (с параметрами алгоритма Диффи-Хеллмана), ServerHelloDone. После передачи ServerHelloDone, сервер ожидает ответа клиента. Клиент должен ответить своим набором сообщений, который описан ниже.

Certificate — это сообщение содержит клиентский сертификат, если он был запрошен сервером. Если у клиента сертификата нет, а сервер его запрашивает, то клиент либо пропускает данное сообщение (SSLv3), либо отвечает пустым сообщением с типом Certificate (TLS). Клиентский сертификат требуется для двухстороннней аутентификации. Все современные браузеры, работающие на десктопе, поддерживают клиентские сертификаты. Клиентский сертификат, в ряде случаев, может заменить пару «логин/пароль» для аутентификации на том или ином онлайн-ресурсе (для выполнения аутентификации клиенту требуется доступ к секретному ключу, который соответствует сертификату; сам по себе сертификат клиента не достаточен для аутентификации).

ClientKeyExchange — клиентская часть обмена данными, которые используются при получении сеансовых ключей. Содержание этого сообщения зависит от того, какой шифронабор выбран. В версиях TLS до 1.3 есть два основных типа — RSA и несколько вариантов протокола Диффи-Хеллмана. В случае использования RSA, клиент генерирует 48-байтовый случайный секрет (при этом первые два байта содержат версию используемого протокола), зашифровывает его открытым RSA-ключом сервера (этот ключ передаётся в составе серверного TLS-сертификата или в сообщении ServerKeyExchange) и передаёт зашифрованные данные на сервер. Сервер может расшифровать значение, используя соответствующий секретный ключ. Данная схема прямо запрещена в TLS 1.3, да и для других версий является скорее исторической, так как обладает целым рядом недостатков. Например, если секретный серверный ключ (от сертификата сервера) станет известен третьей стороне, то она сможет расшифровать ранее записанный TLS-трафик. Тем не менее, обмен сеансовым ключом при помощи RSA продолжает использоваться в некоторых реализациях TLS (кроме 1.3). Современный метод — использование протокола Диффи-Хеллмана. В этом случае, ClientKeyExchange содержит открытый ключ DH. Этот ключ генерируется клиентом либо в соответствии с параметрами, переданными сервером в ServerKeyExchange, либо в соответствии с параметрами, указанными в серверном TLS-сертификате, если последний поддерживает DH. Случай с передачей параметров классического DH в составе сертификата — сейчас является экзотическим, таких сертификатов в «дикой природе» для веба не встречается. Параметры DH (или ECDH), переданные сервером, подписываются серверным секретным ключом; клиент проверяет подпись, используя открытый ключ сервера.

CertificateVerify — если клиент передал в ответ на запрос сервера свой сертификат, то серверу требуется некоторый механизм, позволяющий проверить, что клиент действительно обладает секретным ключом, связанным с сертификатом. Для этого клиент подписывает массив переданных и принятых ранее сообщений Handshake. Такая подпись, если её значение удастся успешно проверить открытым ключом из сертификата, удостоверит факт наличия секретного ключа у клиента. Сообщение передаётся только если был передан клиентский сертификат в сообщении Certificate. В TLS 1.3 аналог этого сообщения перенесён на сторону сервера и служит механизмом ранней аутентификации криптографических параметров (подробнее схема рассматривается ниже, в описании Handshake версии 1.3).

Клиентские сертификаты используются редко. Поэтому в типичном случае клиент, на данном этапе, передаёт одно сообщение — ClientKeyExchange. Это сообщение является, согласно спецификации, обязательным.

Следом за сообщением ClientKeyExchange, если оно было единственным, либо за CertificateVerify, клиент должен передать сообщение ChangeCipherSpec. Важный момент: это сообщение не является сообщением Handshake. Да, в спецификации TLS встречаются такие, не совсем прозрачные, моменты, когда вроде бы логичное течение протокола прерывается специальными «вставками». При разработке TLS 1.3 от этой сомнительной практики отказались, но ChangeCipherSpec всё равно рекомендуется передавать, правда, в качестве фиктивного сообщения, которое просто игнорируется узлами (сообщение нужно для того, чтобы «обмануть» неверно настроенные промежуточные узлы, замаскировав соединение версии 1.3 под предыдущие версии).

ChangeCipherSpec — это специальное сообщение-сигнал, обозначающее, что с данного момента клиент переходит на выбранный шифр, а следующие TLS-записи будут зашифрованы. ChangeCipherSpec (CCS) имеет собственный тип и, соответственно, передаётся в отдельной TLS-записи. Таким образом, CCS имеет весьма важное значение в TLS (но только раньше версии 1.3), отделяя открытую часть сеанса связи от защищённой.

Со стороны клиента установление соединения завершается отправкой сообщения Finished.

Finished. Это сообщение передаётся в зашифрованной TLS-записи, так как следует за сигналом ChangeCipherSpec, который обозначает момент перехода к защищённому обмену информацией. Finished является первым защищённым сообщением в рамках нового сеанса TLS. Вспомните, что к моменту его отправки, если всё прошло успешно, сервер и клиент уже согласовали все необходимые параметры сессии: шифронабор, сеансовый ключ, алгоритм кода аутентификации сообщения. Предназначение сообщений Finished — получить криптографически стойкое подтверждение, что сервер согласовал эти параметры именно с тем узлом, с которым предполагалось, то же самое — и для клиента, который получит сообщение Finished от сервера.

Клиентское Finished содержит отпечаток — значение хеш-функции, — от всех предыдущих сообщений Handshake, отправленных, на данный момент, и клиентом, и сервером. Получив это сообщение в защищённой TLS-записи, сервер может вычислить значение хеш-функции от известных ему предшествовавших сообщений и сравнить результат. Таким образом подтверждается подлинность сообщений и, соответственно, оказываются криптографически защищены выбранный шифронабор и другие параметры соединения. Впрочем, данная защита не лишена недостатков: например, так как сообщения ClientHello и ServerHello не содержат подписей, Finished никак не защищает сессию от атак, основанных на подмене параметров до отправки ChangeCipherSpec. Этот дефект протокола использован в нашумевшей в 2015 году атаке Logjam (об атаках на TLS/SSL мы подробно поговорим ниже). В TLS 1.3 аутентификация параметров сессии начинается раньше: а именно — сервер незамедлительно удостоверяет первую часть сообщений Handshake, включая выбор криптосистем, при помощи серверного сообщения CertificateVerify.

В ответ на Finished со стороны клиента, сервер, в случае успешного установления соединения, отправляет свою пару ChangeCipherSpec и Finished. На стороне клиента полученное серверное сообщение Finished так же используется для проверки, что сообщения Handshake не подверглись модификации активным атакующим, который перехватил канал. Состав Finished сервера отличается от клиентского варианта, так как включает клиентское сообщение Finished (и отличную от клиентской дополнительную строку байтов).

Третьей стороне, активно перехватывающей канал связи, для того, чтобы успешно произвести подмену сообщений Handshake, потребуется вычислить сеансовый ключ и другие секретные параметры (если они использовались), после чего сфабриковать корректное сообщение Finished. Это вычислительно трудная задача, обычно неразрешимая на практике, если выбраны правильные настройки протокола и корректная реализация. Однако, в случае использования нестойких шифронаборов, атакующий может на лету вычислить секретный сеансовый ключ и успешно подделать сообщение Finished.

После того как клиент и сервер обменялись парами ChangeCipherSpec и Finished — защищённое соединение успешно установлено и данные могут передаваться в защищённой форме.

Посмотрим на ServerHello (TLS 1.1) и последующие сообщения сервера в деталях, примером послужит ответ сервера на сообщение ClientHello, которое разбиралось выше. В этом примере несколько сообщений TLS передаются в одной TLS-записи.

Смещение Байты Комментарий (десятичное) (шестнадцатеричное представление) 0000 16 03 02 ; Тип записи - Handshake (0x16) - версия TLS 1.1 (0x0302). 0003 07 02 ; Длина пакета данных (0x0702 = 1794 байта - в этой записи содержатся все отправленные сервером сообщения - ServerHello, Certificate, ServerKeyExchange, ServerHelloDone - отсюда и такая длина). ServerHello. Начало сообщения 0005 02 ; Тип сообщения: ServerHello (02). 0006 00 00 46 ; Длина данных: (0x000046 = 70 байтов - это данные ServerHello). 0009 03 02 ; Версия протокола: 0x0302 - TLS 1.1. 0011 55 dc ; 32 байта ServerRandom, в начале поля сервер указывает timestamp. [. ] 0043 20 ; Длина SessionID - (0x20 = 32 байта). 0044 81 19 ; 32 байта, содержащие переданный сервером идентификатор сессии (SessionID). [. ] 0076 c0 14 ; Выбранный сервером шифронабор - 0xc014 - TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA (протокол Диффи-Хеллмана на эллиптических кривых - для сеансового ключа, RSA - для подписи, AES с 256-битным ключом в режиме CBC в качестве потокового шифра, SHA-1 для MAC). 0078 00 ; Выбранный сервером метод сжатия - 00 - null. Certificate. Начало сообщения 0079 0b ; Сообщение Certificate (тип - 0x0b = 11). 0080 00 05 21 ; Длина сообщения (0x000521 = 1313 байтов). 0083 00 05 1e ; Длина данных сертификатов (0x00051e = 1310 байтов). 0086 00 05 1b ; Длина поля с сертификатом. Каждый из сертификатов, указанных в сообщении Certificate, предваряется тремя байтами, содержащими длину записи данного сертификата. Также передаётся общая длина набора сертификатов - отсюда и эти "вложенные" поля с числом байтов. 0089 30 82 05 17 30 ; Байты, составляющие сертификат (сам сертификат здесь не приводится). Сертификат передаётся сервером в бинарном представлении, с использованием определённого кодирования. На практике это означает, что передаются сертификаты в общепринятом формате DER, который поддерживается большинством утилит, например из пакета OpenSSL и др. [. ] ServerKeyExchange. Начало сообщения 1396 0c 00 01 8b ; Сообщение ServerKeyExchange (тип - 0x0c = 12), длина данных (0x00018b = 395 байтов). Так как выбран шифронабор с ECDHE, то сообщение ServerKeyExchange содержит параметры именно для алгоритма ECDHE. Каких-то специальных флагов, обозначающих ServerKeyExchange как ECDHE, - не предусмотрено, всё определяется шифронабором. Использование DH на эллиптических кривых описано в RFC 4492 (https://tools.ietf.org/html/rfc4492). 1400 03 ; Тип кривой (0x03 - типовая именованная кривая). 1401 00 19 ; Идентификатор выбранной сервером кривой (0x0019 - secp521r1, реестр кривых ведёт IANA, каждая из типовых кривых содержит в своём определении необходимые для DH параметры, которые строго зафиксированы: генератор, разрядность группы точек и др.). 1403 85 ; Длина поля публичного ключа, которое идёт следом (0x85 = 133 байта). 1404 04 00 8f 96 86 ; 133 байта, представляющие собой публичный ключ ECDHE сервера. Публичный ключ - это точка на кривой, которую сервер вычислил, используя параметры кривой. В соответствии с форматом записи точек, указанным клиентом в расширении ClientHello, передаются аффинные координаты точки (x,y) (запись предваряется заголовком). Клиенту параметры кривой известны потому, что используется типовая кривая. [. ] 1537 01 00 ; Длина подписи, соответствующей параметрам DH (0x0100 - 256 байтов). За значением открытого ключа DH следует серверная подпись, выполненная по алгоритму и с ключом, которые соответствуют указанным в серверном сертификате (в нашем случае - RSA). В TLS 1.2 формат представления подписи несколько другой: в составе ServerKeyExchange добавлены поля, обозначающие используемый для генерации подписи на параметрах DH набор из хеш-функции и криптосистемы электронной подписи (например, RSA+SHA-256). 1539 25 23 f5 ; Значение подписи (полностью не приводится). [. ] ServerHelloDone. Начало сообщения 1795 0e 00 00 00 ; Сообщение ServerHelloDone (тип - 0x0e = 14). Это сообщение имеет нулевую длину, поэтому следом за типом идут три байта с нулевыми значениями (это кодирующие длину байты).

Сокращённый формат Handshake в TLS 1.2 (и раньше)

Установление TLS-соединения — многоступенчатый процесс, достаточно сложный и требующий проведения заметного количества вычислительных операций, особенно жадными в плане процессорного времени оказываются операции проверки подписей и других действий с асимметричными криптосистемами. Каждая итерация, связанная с отправкой запроса и получением ответа, вносит дополнительную задержку, а для массовых сервисов миллисекунды ожидания превращаются в весьма ощутимые затраты на оборудование. Для экономии ресурсов существует сокращённая версия Handshake.

В составе ServerHello сервер передаёт SessionID — идентификатор новой сессии. Этот идентификатор может быть использован клиентом позже, в составе ClientHello (см. выше). Предполагается, что на стороне сервера (и клиента) сохранены необходимые параметры, которые могут быть быстро восстановлены, возобновив тем самым сессию.

Client Server ClientHello --------> ServerHello [ChangeCipherSpec] Application Data Application Data Установление соединения по сокращённой схеме Источник: RFC 5246

В случае использования сокращённой схемы, сразу после получения ClientHello, содержащего валидный идентификатор сесcии SessionID, сервер отвечает сообщениями ServerHello, ChangeCipherSpec и Finished (этот вариант, кстати, напоминает Handshake TLS 1.3). После того как клиент пришлёт свои CCS и Finished, сессия возобновляется и узлы могут начать обмен данными в защищённом режиме.

Сокращённый сценарий содержит существенно меньше сообщений, позволяет не использовать вычислительно затратные операции проверки подписей и генерации общего секрета, кроме того, из-за меньшего количества сообщений заметно снижается задержка при установлении соединения (экономится время, требуемое на отправку пакетов от клиента к серверу и обратно). Современные браузеры широко используют сокращённый Handshake (но не обязательно с версиями до 1.3). Сессии могут сохраняться на серверах в течение нескольких минут, нескольких часов, а возможно — дольше.

Сейчас используются и другие способы возобновления сессий. Например, RFC 5077 вводит понятие тикета сессии (TLS Session Ticket) — это расширение, в составе которого сервер передаёт клиенту зашифрованное представление серверного контекста TLS. Клиент может восстановить сессию, передав в составе расширения ClientHello сохранённый тикет.

Общие замечания

После того как клиент и сервер установили соединение (по полной или сокращённой схеме), они обмениваются TLS-записями с типом Application Data, каждая такая запись содержит блок данных, зашифрованный симметричным шифром, а также код аутентификации сообщения. Код аутентификации защищает сообщение от изменения. Клиент и сервер самостоятельно ведут учёт полученных и переданных блоков.

TLS имеет ряд важных, и достаточно общих, криптографических особенностей: во-первых, этот протокол никак не скрывает факт установления соединения (как указано выше, системы DPI могут уверенно детектировать начало сеанса TLS при помощи простых правил-фильтров); во-вторых, в TLS возможны утечки метаинформации: число переданных блоков, различные предупреждения, передаваемые в открытом виде — всё это позволяет пассивному наблюдателю сделать некоторые выводы о характере передаваемой информации и, в случае веба, о типе совершаемых пользователем на веб-ресурсе действий. TLS лишь более или менее надёжно защищает от перехвата и подмены саму передаваемую информацию.

Повторное проведение Handshake

Во время работы в рамках TLS-сессии клиент и сервер могут столкнуться с необходимостью повторно провести Handshake. Такой случай предусмотрен протоколом. Хрестоматийная ситуация, когда это может потребоваться, следующая: после того как установлено TLS-соединение, клиент, использующий HTTP, запрашивает документ по некоторому URL, однако этот URL требует дополнительной авторизации с использованием клиентского сертификата. Клиентский сертификат может быть передан только в составе сообщения Handshake, поэтому сервер отправляет клиенту сообщение HelloRequest, требующее повторного обмена сообщениями Handshake (уже с клиентским сертификатом). Клиент может инициировать новую сессию в любой момент, передав сообщение ClientHello (в TLS 1.3 эта возможность исключена). Так как узлы уже согласовали TLS-соединение, обмен сообщениями повторного Handshake будет проводиться в защищённом виде. В примере с клиентским сертификатом это означает, что сертификат не будет виден прослушивающей канал стороне.

Предупреждения (Alert)

Спецификация TLS предусматривает обмен сообщениями с типом Alert. Это предупреждения и сообщения об ошибках. Например, в случае, если сервер не смог корректно разобрать сообщение ClientHello, он отвечает сообщением Alert, содержащим код ошибки Parse Error. Сообщения Alert иногда могут быть использованы в составе атак на TLS-узлы: так, при помощи отправки этих сообщений можно «подвешивать» сессию, когда перехватывающему устройству требуется время на, например, вычисление ключа.

После того, как узлы согласовали криптографический контекст и обменялись сообщениями ChangeCipherSpec — сообщения Alert передаются в зашифрованном виде. То есть, с этого момента содержание предупреждения не может быть прочитано прослушивающей трафик стороной, но сам тип записи — Alert — всё равно передаётся в открытом виде (кроме TLS 1.3), что, соответственно, может приводить к утечке информации о состоянии узлов и соединения.

Сеансовые ключи

Асимметричные криптосистемы (с открытым ключом) не подходят для быстрой передачи потоков данных. Поэтому TLS использует внутри сессии симметричные шифры. Обычно это блочные шифры, работающие в режиме, сходном с потоковым (например, GCM). Есть несколько основных способов выработки общих секретных данных для сеансового ключа. О симметричных сеансовых ключах узлы договариваются в процессе установления соединения (Handshake). Основные методы вычисления общего секрета в TLS рассмотрены выше, осталось обсудить некоторые подробности. Прежде всего: симметричных ключей используется пара — один для передаваемых сообщений, второй — для принимаемых. Серверному ключу для передаваемых сообщений (Write) соответствует клиентский ключ для принимаемых (Read), и наоборот. В TLS 1.3 используются несколько уровней ключей (для Handshake, для защиты трафика), каждый из уровней включает пару значений.

Основа ключей — общий секрет Master Secret — генерируется из нескольких составляющих: так называемый Premaster Secret, ClientRandom и ServerRandom. Эти составляющие изменяются от сессии к сессии. В TLS 1.2 и раньше Premaster Secret согласуется в рамках Handshake. Это либо последовательность случайных байтов, зашифрованная открытым ключом сервера (RSA), либо значение, полученное в результате обмена по протоколу Диффи-Хеллмана (основной способ сейчас). Master Secret — это массив из 48 байтов, получаемый в результате применения клиентом и сервером к только что описанным составляющим псевдослучайной функции, определённой спецификацией. То есть, рассматриваемые как последовательности байтов значения Premaster Secret, ClientRandom и ServerRandom поступают на вход функции (аргументы), а результатом вычисления является последовательность из 48 байтов, которая считается псевдослучайной. «Псевдослучайность» тут означает, что не обладающая дополнительными данными сторона не может при помощи практических вычислений отличить эту последовательность от действительно случайной. Псевдослучайная функция (PRF) TLS 1.2 построена на базе хеш-функции SHA-256 (либо может быть использована более «мощная» хеш-функция, указанная в составе шифронабора). Предыдущие версии TLS используют конструкцию на базе сочетания MD5 (которая давно не считается криптографически стойкой) и SHA-1 (которую перестали считать достаточно стойкой в 2015 году). При этом способ использования MD5 и SHA-1 для генерации сеансового ключа не приводит к возникновению уязвимостей, связанных с известными сейчас (2023) недостатками этих функций.

RFC 5246 определяет Master Secret для TLS 1.2 следующим образом:

master_secret = PRF(pre_master_secret, "master secret", ClientHello.random + ServerHello.random)[0..47];

Master Secret — это ещё не сеансовый ключ. Дело в том, что разные шифры требуют разных ключей и дополнительных данных (например, инициализирующих векторов). Эти ключи и данные вычисляются на основе Master Secret с использованием той же псевдослучайной функции. Делается это следующим способом (TLS 1.2):

  1. для выбранного шифронабора определяется количество байтов, необходимое для получения ключа и инициализирующей информации;
  2. нужное число байтов (Key Block) получается на оcнове Master Secret, ServerRandom, ClientRandom при помощи последовательных вызовов всё той же псевдослучайной функции;
  3. полученный Key Block разбивается на подмножества, нужные для инициализации и работы шифра, а также для вычисления кода аутентификации сообщений (MAC). При этом могут различаться ключи и векторы инициализации сервера и клиента (но полный набор криптографических параметров известен обоим узлам).

Логика только что описанной схемы в базовых чертах применима и к TLS 1.3, однако в новой версии механизм формирования симметричных ключей сложнее, в частности, введено понятие «ключевого контекста», которое включает в себя значения и самих сообщений Handshake. Подробнее этот механизм рассмотрен в специальном разделе, в рамках описания установления соединения TLS 1.3.

Зашифрование полезной нагрузки осуществляется на уровне TLS-записей.

Большинство методов получения исходных данных сеансового ключа так или иначе оперируют публичным ключом сервера. На практике этот ключ использует почти 100% TLS-сессий. Публичный ключ передаётся сервером в сертификате. Помимо рассмотренных выше вариантов RSA и Диффи-Хеллмана, возможны экзотические схемы получения общего секрета:

  1. PSK — pre-shared key. Схема основана на использовании общего секретного ключа и симметричной криптосистемы, при условии, что ключ был согласован заранее;
  2. временный ключ RSA — исторический метод, предполагавший создание сеансового ключа RSA. Сейчас данный метод не используется, однако его поддержка послужила основой для атаки FREAK, опубликованной в 2014 году;
  3. SRP — протокол SRP (Secure Remote Password), RFC 5054. Протокол, позволяющий сгенерировать общий симметричный секретный ключ достаточной стойкости на основе известного клиенту и серверу пароля, без раскрытия этого пароля через незащищённый канал;
  4. Анонимный DH — анонимный вариант протокола Диффи-Хеллмана, в котором не используется подпись на серверных параметрах. Такая схема подвержена атаке типа «человек посередине», встречается крайне редко (дополнительная защита от атак может быть обеспечена при помощи сохранения отпечатка ключа);
  5. DH с сертификатом — вариант DH, в котором параметры (модуль, генератор и открытый ключ сервера) определены в серверном сертификате. Этот метод является историческим, требует специального сертификата и на практике не встречается. Основное его отличие от используемых сейчас вариантов (нередко называемых «эфемерным Диффи-Хеллманом», хотя подобного термина следует избегать) состоит в том, что серверный открытый ключ протокола Диффи-Хеллмана оказывается зафиксирован: именно он входит в сертификат и подписывается удостоверяющим центром. Это означает, что схема не обладает прогрессивной секретностью. Сервер всякий раз использует один и тот же секретный ключ Диффи-Хеллмана, а раскрытие этого ключа позволяет расшифровать ранее записанный трафик TLS.

Протокол Диффи-Хеллмана

Современный метод генерации общего сеансового секрета — это протокол Диффи-Хеллмана (DH). Использование DH, прежде всего, позволяет добиться прогрессивной секретности (Perfect Forward Secrecy, PFS), когда раскрытие серверного ключа асимметричной криптосистемы (RSA или ECDSA) не приводит автоматически к раскрытию ранее записанного трафика.

Протокол Диффи-Хеллмана — важнейший элемент современных реализаций TLS. Этот протокол имеет огромное значение для множества других защищённых протоколов Интернета, для прикладной криптографии в целом. Протокол не является шифром или алгоритмом электронной подписи. На его основе можно построить и асимметричную криптосистему, и схему электронной подписи, но в TLS он используется с другой целью: этот протокол позволяет участникам обмена информацией договориться об общем секретном ключе через открытый канал связи. Задача Диффи-Хеллмана, лежащая в основе классической версии протокола, прямо связана с алгебраической задачей дискретного логарифмирования в конечной группе ― на вычислительной сложности этой задачи и построена защита протокола от перехвата секретного ключа.

Основная идея протокола DH может быть сформулирована достаточно просто. Две стороны, желающие получить общий секрет, очевидно, могут сгенерировать собственные, локальные, секреты, например, то или иное число. Предположим, что у нас есть некоторая однонаправленная функция — то есть, можно легко вычислить значение функции для заданного аргумента, но обратить вычисления и узнать аргумент по значению — сложно. Тогда можно было бы устроить алгоритм таким образом, чтобы договаривающиеся об общем секрете стороны передавали по открытому каналу друг другу значения функции от секретных аргументов, проводили над этими значениями и аргументами собственные вычисления и, в результате применения некоторых преобразований, могли бы каждая прийти к одному и тому же значению. Просматривающая же коммуникации третья сторона видела бы только значения однонаправленной функции, без возможности обратить её и узнать секрет. Успешная реализация такого протокола и есть схема Диффи-Хеллмана.

Важно отметить, что схема представляет собой протокол верхнего уровня, она не зависит от используемых математических примитивов, лишь бы они обладали нужными свойствами. Схема может быть реализована на базе самых разных математических систем, а не только, например, на группе точек эллиптической кривой. Самое интересное, что именно эта идея используется в самых современных криптосистемах, предлагаемых в качестве замены классическим в постквантовую эпоху. Обобщение схемы Диффи-Хеллмана позволяет строить криптосистемы, обладающие стойкостью к взлому с использованием (гипотетического) универсального квантового компьютера. Такие криптосистемы относятся к постквантовой криптографии. То есть, несмотря на то, что используемые сейчас варианты DH уязвимы для атак с помощью квантового компьютера, ту же самую математическую схему можно реализовать в варианте, обладающем постквантовой стойкостью, перенеся без изменений на другие математические объекты. Поэтому иногда встречающиеся утверждения, что протокол DH не обладает постквантовой стойкостью, заметно искажают реальное положение дел: уязвимы лишь конкретные варианты протокола, но не он сам. Причём речь здесь идёт о математической реализации протокола, о самом алгоритме, а не о конкретном воплощении в программном коде.

Вернёмся к использованию DH в TLS. Сейчас (2023) распространены два варианта протокола. В классическом случае, DH работает в «обычной» конечной группе, задаваемой простым числом P, которое называется модулем. «Обычная» — довольно условное определение: имеется в виду, что классический DH работает в арифметике остатков, где числа берутся по модулю некоторого достаточно большого простого числа. Такие операции более привычны, чем второй вариант DH, который использует группу точек эллиптической кривой.

Под «группой» здесь понимается алгебраическая структура — множество с бинарной операцией, подчиняющейся некоторому набору аксиом. Конечная группа — это группа с конечным числом элементов. В принципе, для понимания принципов работы классического варианта DH достаточно знакомства с арифметикой остатков.

Рассмотрим классический вариант DH подробнее. Здесь группа, в которой будут проводиться операции вычисления общего секрета TLS, это всего лишь множество остатков от деления на некоторое простое число, которое называют модулем. Это обязательно достаточно большое простое число. Большое — означает, что разрядность его записи превышает 1000 бит, а современная рекомендация для классического варианта — не менее 2048 бит. В TLS 1.2 сервер передаёт это число (значение модуля) в составе сообщения ServerKeyExchange, если используется классический алгоритм DH. Модуль полностью определяет группу, поэтому каких-то дополнительных параметров передавать не нужно. На практике веб-серверы используют то или иное типовое значение модуля. Модуль не является секретным — он передаётся в открытом виде. Таким образом, известны группы, используемые большинством веб-серверов, поддерживающих DH (классический). Вообще говоря, уникальные группы DH рекомендуется генерировать при начальной настройке TLS, это несложно сделать стандартными утилитами. Тем не менее, не так давно наиболее распространённая типовая группа имела разрядность в 1024-бита, что не слишком много. Вместе с задающим группу модулем, сервер передаёт другой открытый параметр — генератор (это тоже число — см. подробности ниже), — а также свою часть обмена Диффи-Хеллмана — открытый ключ (принцип его вычисления рассмотрен ниже).

Второй вариант протокола Диффи-Хеллмана — «эллиптический», он основан на эллиптических кривых. (Элементарный обзор некоторых основ практического математического аппарата, который стоит за криптографией на эллиптических кривых, дан в «Приложении А».) Математические операции протокола DH в обоих случаях эквивалентны, отличие кроется в используемых группах: эллиптический вариант работает в группе точек эллиптической кривой. Такая группа может быть построена при помощи заданной на кривой операции, называемой сложением точек. Следует понимать, что здесь важно не название, а свойства операции, с таким же успехом её можно было назвать умножением точек. Собственно, различают два эквивалентных подхода к обозначению групповых операций: мультипликативный (умножение) и аддитивный (сложение). Обычно, применительно к TLS (и прикладной криптографии), в случае классического протокола DH — используют мультипликативный вариант и говорят об умножении (числа тут действительно умножаются, в привычном школьном смысле) и возведении в степень (экспонента); в случае эллиптического — аддитивный, и говорят о сложении точек и нахождении кратного (умножение на скаляр). Это чисто терминологическое отличие, никак не связанное со стойкостью и другими особенностями протокола.

Итак, операция сложения точек на кривой ставит в соответствие двум точкам — третью, называемую их суммой. На этой операции строится алгоритм удвоения точки и умножения на скаляр (целое положительное число, не являющееся, соответственно, точкой на кривой). Также вводится нейтральный элемент — в его роли выступает «бесконечно удалённая точка». Эллиптическая кривая, в общем смысле, обладает непрерывностью, но в случае с протоколом Диффи-Хеллмана в TLS она рассматривается только в «целых» (или, если хотите, «диксретных») точках, множество которых задано определённым образом. Прикладная особенность группы точек эллиптической кривой состоит в том, что решение задачи дискретного логарифмирования (обратной задачи для основы протокола DH) здесь обычно сложнее, чем в «обычной» группе классического DH, что позволяет использовать ключи меньшей разрядности с сохранением стойкости. Впрочем, для понимания математического принципа протокола Диффи-Хеллмана детали работы с эллиптическими кривыми не требуются.

Протокол DH на «обычной» группе (классический) работает следующим образом. Для того чтобы получить общий секретный ключ, стороны сначала выбирают общие параметры Диффи-Хеллмана ― это модуль, задающий группу (простое число), а также некоторый элемент этой группы, называемый генератором — соответственно: P и G (то есть, два целых числа, меньше модуля). Параметры DH открыты и считаются известными третьей стороне. На следующем шаге каждая из сторон выбирает собственное секретное целое число a (и, соответственно, b) и вычисляет значение A = G a mod P (соответственно, B = G b mod P). То есть, все операции проводятся по модулю P (это «взятие остатка» в школьном смыле: числа умножаются обычным способом, а от результата берётся остаток от деления на P), что, собственно, и отображает их результаты в элементы группы. Далее стороны обмениваются по открытому каналу значениями A, B и вычисляют A b mod P и B a mod P, соответственно. Полученные значения равны, так как, из свойства степеней, A b = (G a ) b = B a = (G b ) a = G ab . Таким образом, стороны получили общий секретный ключ G ab .

Если вернуться к описанной выше основной идее протокола, то операция возведения в степень (по модулю) выступает в роли однонаправленной функции, значения которой передаются по открытому каналу. Свойство групповой операции (в данном случае, эквивалентное более привычному свойству степеней), позволяет сторонам, осуществляющим обмен значениями, прийти к одинаковому результату (G ab ). В случае TLS, сервер передаёт в сторону клиента параметры Диффи-Хеллмана и свой открытый ключ (A), удостоверяя эти значения собственной электронной подписью (либо RSA, либо ECDSA). Подпись вычисляется от ключа, открытая часть которого указана в сертификате сервера. Прослушивающая канал сторона знает значения P, G, A и B. Но для того, чтобы определить значение секретного ключа, необходимо вычислить a или b, решив относительно x уравнение вида A = G x mod P. Стоящая за решением этого уравнения классическая задача и называется задачей дискретного логарифмирования в конечной группе. В общем случае, эта задача вычислительно сложна для чисел достаточно большой разрядности (1024 бита и выше, для «классического» протокола DH), поэтому возведение в степень на практике оказывается однонаправленным.

Фундаментальная причина сложности данной операции сходна с общими проблемами деления (или вычитания, тут всё зависит от используемой терминологии) в группах: грубо говоря, деление представляет собой операцию поиска среди элементов группы такого, который при умножении на известный делитель давал бы делимое (поиск обратного элемента). Ситуация эквивалентна привычному делению из курса начальной школы: чтобы разделить 15 на 3 нужно найти такое число, которое при умножении на 3 давало бы 15. Если известны некоторые свойства группы, позволяющие построить её арифметическую структуру; или группу удаётся рассмотреть в составе «большей» структуры, то операцию деления можно оптимизировать, используя тот или иной «быстрый» пошаговый алгоритм, отбрасывающий из перебора заведомо неподходящие элементы. Хорошо известным примером такой оптимизации является школьное «деление столбиком». Именно поэтому в случае с современными вариантами DH работает квантовый алгоритм Шора, использующий квантовое представление структуры группы (кольца, если говорить строго), измерение которого даёт результат, позволяющий уже классическим методом очень быстро выполнить дискретное логарифмирование.

Практическая применимость протокола Диффи-Хеллмана основывается на том, что знание секретного значения позволяет быстро вычислить нужную экспоненту. Действительно, предположим, что требуется вычислить A = G m . На первый взгляд, для этого необходимо умножить G на себя m-1 раз: G*G*. *G. Казалось бы, атакующая сторона тут оказывается в таком же положении, как и стороны, использующие протокол: атакующий может начать умножать G (это открытый параметр) и продолжать вычисления до тех пор, пока не получит искомое значение A (которое перехватил). Таким образом можно определить значение m. Однако реальная ситуация отличается. Дело в том, что, зная секретный параметр m, вычислить G можно гораздо быстрее. Простейший пример: предположим, что нам нужно вычислить G 5 , показатель 5 заранее известен. G 5 = G*G*G*G*G. Это четыре операции умножения, но c другой стороны, значение G 2 можно записать, и использовать несколько раз. Получаем: G 2 *G 2 *G, а это уже только три умножения (учитывая G*G). То есть, зная значение показателя, можно применить быстрые алгоритмы (см. алгоритмы Монтгомери и др.) и получить огромный выигрыш в числе операций по сравнению с атакующим, который должен проверить все показатели, что для разрядности в сотни бит потребует слишком много времени.

Для протокола DH, работающего на эллиптической кривой, вместо модуля P задаётся сама кривая (с дополнительными параметрами); вместо возведения в степень — используется умножение на скаляр (то есть, вычисляется кратное для точки: если мы умножаем точку A на значение 5, это означает, что на кривой вычисляется точка 5A = A+A+A+A+A). В TLS используются именованные кривые, параметры которых заранее известны сторонам. Генератором, в эллиптическом случае, является точка кривой. Однако логика протокола от этих особенностей не зависит. Операции DH на эллиптической кривой просто будут записаны в аддитивной форме: Ab = (Ga)b = Ba = (Gb)a = Gab. Обратите внимание на скобки в предыдущем выражении: они указывают на «ассоциативность», обобщение которой и позволяет перенести схему Диффи-Хеллмана на другие математические объекты, если для них такая «ассоциативность» выполняется. Конечно, должен работать и описанный в предыдущем абзаце механизм ускорения вычислений при известном секрете. Для группы точек эллиптической кривой он работает, сводя основную часть вычислений к некоторому количеству удвоений точки.

Итак, практическая полезность DH строится на сложности задачи дискретного логарифмирования в конечной группе. Известно, что при наличии больших, но вполне доступных, вычислительных мощностей (не квантовых), для 1024-битной «классической» (не «эллиптической») группы можно уже сейчас предвычислить арифметическую структуру, потратив пару лет работы суперкомпьютера и сохранив результаты в специальных таблицах. После этого вычислять дискретный логарифм в конкретной группе можно достаточно быстро (за часы, а возможно, просто на лету), особенно, если вы используете специализированную многопроцессорную систему. Это означает, что можно расшифровать записанный ранее трафик TLS-сессий (а также других протоколов, использующих DH). Дело в том, что сеансовый ключ, если вы умеете отыскивать дискретный логарифм, элементарно вычисляется из ключа DH, который передаётся в открытом виде. Предвычислить нужную структуру можно только для заранее известной группы, поэтому для атакующего важно, чтобы TLS-серверы использовали типовые параметры. При этом, для тех, у кого ресурсов мало (кто не является специализированным агентством, например), группа остаётся вполне стойкой. (Для групп точек эллиптической кривой подобных алгоритмов быстрого дискретного логарифмирования на настоящий момент в открытой печати не опубликовано. С фундаментальной точки зрения это, скорее всего, обусловлено тем, что для произвольных эллиптических кривых не удаётся найти некоторых аналогов простых чисел, которые помогли бы доступным, в плане вычислений, способом вложить группу кривой в другое множество с дополнительной структурой, где значение логарифма отыскать проще. Необходимо отметить, что это верно не для всякой эллиптической кривой и не для всяких параметров: в целом ряде случаев такое вложение можно вычислить на практике.)

Разновидность DH в группе точек эллиптической кривой называется ECDH. Это рекомендуемый сейчас вариант алгоритма, в современных реализациях TLS он получил большое распространение. Так как отыскание дискретного логарифма в группе точек эллиптической кривой вычислительно сложнее, можно использовать ключи с меньшей разрядностью. Высокую секретность, согласно современным представлениям, обеспечивает группа эллиптической кривой с разрядностью 192 и более бит. Также алгоритм позволяет безопасно использовать общую кривую, а не генерировать новую для каждого сервера. По крайней мере, современная ситуация такова, что рекомендовано использовать хорошо известные кривые из утверждённого списка (в TLS 1.2, 1.1 возможно использование собственных параметров, они будут передаваться в сообщениях Handshake; в TLS 1.3 — набор зафиксирован спецификацией). Распространённый случай – кривая secp256r1, предлагающая разрядность 256 бит. Если группу классического DH в TLS легко поменять – модуль и генератор непосредственно передаются в сообщении сервера и могут быть любыми, – то для типовых эллиптических кривых всё сильно сложнее: все параметры здесь фиксированы заранее, клиент и сервер могут договориться только о выборе кривой из ограниченного списка.

В TLS версий до 1.3 параметры DH всегда задавал сервер. Эти параметры, как сказано выше, подписываются серверным ключом, что необходимо для того, чтобы параметры не могли быть заменены в момент передачи. Хотя сообщение Finished защищает весь обмен Handshake, активный атакующий мог бы подменить параметры DH на свои собственные, перехватив соединение и, в дальнейшем, сгенерировав для клиента и сервера разные, но корректные сообщения Finished — протокол DH сам по себе не защищён от атаки типа человек посередине (схема, сходная с только что описанной, применяется в атаке Logjam). Поэтому подпись на параметрах крайне важна. В TLS 1.3 протокол DH используется уже на начальном шаге установления соединения, поэтому параметры подписываются в составе прочих сообщений, а подпись передаётся сервером в сообщении CertificateVerify. Другое важное отличие 1.3 в том, что здесь параметры DH согласуются узлами, причём, инициатива принадлежит клиенту: он передаёт список поддерживаемых групп (а это и эллиптические, и «мультипликативные», классические варианты) в расширении сообщения ClientHello, так же, но в другом расширении, передаются и открытые ключи клиента. Сервер выбирает подходящие параметры.

Широко используются аббревиатуры ECDHE и DHE, то есть, варианты записи, оканчивающиеся буквой E. Эта буква обозначает то, что протокол DH используется для выработки временного сеансового ключа, от английского ephemeral («эфемерный»). То есть, E — подчёркивает то, что ключ не является постоянным (однако, как уже отмечено выше, не следует использовать для обозначения этого свойства прямой русский перевод — «эфемерный»: в русскоязычном варианте ключ называется «временным» или «сеансовым»). Почему потребовалось отдельно выделять «временные ключи»? Причина в том, что в TLS определены варианты соединений, использующих постоянный серверный открытый ключ DH, заданный в сертификате. Сейчас такие схемы на практике не встречаются, поэтому ключ, полученный в результате обмена сообщениями DH, всегда будет временным. Это, однако, не означает, что данный ключ каким-либо образом автоматически исчезает после закрытия соединения: во-первых, ключ может не удаляться из памяти сервера или направляться в долговременное хранилище, по тем или иным причинам; во-вторых, ключ можно восстановить из записи трафика, при условии, что третьей стороне известен (или она может вычислить) соответствующий секретный параметр Диффи-Хеллмана. Кроме того, ничто не препятствует серверу просто не обновлять «временный» ключ, каждый раз используя одно и то же значение при установлении соединения — то есть, сделав ключ статическим.

Пример серверного сообщения ServerKeyExchange, содержащего параметры DH (в «классическом» варианте) и подпись на этих параметрах. (Вариант на эллиптической кривой рассматривался в анализе дампа трафика выше.)

Смещение Байты Комментарий (десятичное) (шестнадцатеричное представление) 0000 16 03 01 ; Handshake, TLS 1.0. 0003 03 0d ; Длина сообщения: 0x030d = 781 байт. 0005 0c ; Сообщение ServerKeyExchange. 0006 00 03 09 ; Длина данных: 0x000309 = 777 байт. 0009 01 00 ; Длина значения модуля P (из параметров DH): 0x0100 = 256 байт (2048 бит). 0011 ff ff ff. ; Блок со значением модуля P (полностью не приводится). [. ] 0257 00 01 ; Длина блока со значением генератора G: 1 байт. 0259 02 ; Значение генератора: 2. 0260 01 00 ; Длина блока серверной части обмена DH: 0x0100 = 256 байт. 0261 5c fb 83. ; Блок со значением серверной части DH (полностью не приводится). [. ] 0517 01 00 ; Длина блока подписи (RSA) на параметрах DH - 256 байт, соответствует серверному ключу из сертификата в 2048 бит. 0519 c4 bc 5d. ; Начало блока, содержащего значение подписи.

TLS 1.3: первоначальное соединение (Handshake)

В TLS 1.3 от предыдущих версий унаследованы только базовые принципы установления соединения: сохранились роли узлов (соединение инициирует клиент), не изменилась последовательность ClientHello — ServerHello, присутствует сообщение-сигнал Finished. Однако на этом сходство заканчивается. В TLS 1.3 сокращено и общее число сообщений Handshake, и число сообщений, передаваемых в открытом виде: узлы практически сразу переходят на зашифрованный обмен. Поэтому из схемы установления соединения удалён сигнал ChangeCipherSpec — он больше не требуется (как ни странно, cам «сигнал» при этом остался и может передаваться узлами, см. ниже). Изменилась роль сообщения CertificateVerify — при передаче со стороны сервера оно удостоверяет сообщения первой части Handshake.

Схема полного Handshake TLS 1.3 выглядит следующим образом:

Client Server Key ^ ClientHello Exch | + key_share* | + signature_algorithms* | + psk_key_exchange_modes* v + pre_shared_key* --------> ServerHello ^ Key + key_share* | Exch + pre_shared_key* v ^ Server v Params ^ | Auth v <-------- [Application Data*] ^ Auth | v --------> [Application Data] [Application Data] Установление соединения по полной схеме TLS 1.3 Источник: RFC 8446

Здесь символом ‘*’ отмечены необязательные сообщения (передаются в зависимости от контекста), а в фигурных скобках даны сообщения Handshake, которые передаются в зашифрованном виде. Квадратные скобки обозначают данные полезной нагрузки, которые передаются в зашифрованном виде, но с использованием другого набора ключей шифрования. Обратите внимание: уже первый ответ сервера — содержит зашифрованные данные. В TLS предыдущих версий — практически все существенные Handshake-сообщения передаются в открытом виде.

В протоколе установления соединения TLS 1.3 выделяются три фазы: выработка начального значения общего криптографического секрета (ключей), определение параметров соединения, аутентификация (сервера и клиента).

К первой фазе относятся ClientHello и ServerHello (а также их расширения, обозначенные на схеме символом ‘+’). Результатом обмена сообщениями в первой фазе является получение первого секрета (в терминах спецификации исходный секрет называется handshake_traffic_secret). На основе этого секрета, используя дополнительно сами сообщения, переданные к этому моменту, стороны получают первый набор симметричных ключей. Эти ключи предназначены для зашифрования сообщений Handshake, начиная с серверного EncryptedExtensions. Например, серверный сертификат в TLS 1.3 передаётся в зашифрованном виде. Это означает, что сторона, прослушивающая канал связи, но не имеющая ключей, не сможет определить, что за сертификат был предоставлен сервером (и был ли он предоставлен вообще — истинная длина сообщений может быть скрыта при помощи дополнения их нулевыми байтами, это также определено спецификацией 1.3). Первая фаза завершается передачей ServerHello и обязательных расширений.

Вторая фаза включает серверные сообщения EncryptedExtensions и, при необходимости аутентификации клиента, CertificateRequest. Новое сообщение — EncryptedExtensions — добавлено в TLS 1.3.

В третьей фазе, представленной группами сообщений Certificate, CertificateVerify и Finished, происходит аутентификация сервера и клиента. Как и в предыдущих версиях TLS, аутентификация может быть полностью исключена (анонимный режим), однако типичный сценарий использования подразумевает, по крайней мере, аутентификацию сервера клиентом. При этом в TLS 1.3 сервер может перейти к отправке данных полезной нагрузки (Application Data на схеме) непосредственно после серверного Finished — это возможно потому, что к этому моменту сервером уже получен первый набор симметричных ключей.

В TLS 1.3 появился новый механизм опознавания используемой версии протокола. Поля, содержавшие номер версии в предыдущих версиях, сохранены в статусе «исторических», их значения зафиксированы. Версия же 1.3 (её номер: 0x0304) передаётся в специальном расширении сообщений ClientHello/ServerHello. Данное расширение называется supported_versions, а его наличие является одним из признаков того, что клиент (или сервер) будут использовать версию TLS 1.3. Это важная особенность: способо обозначения версий теперь перенесён на другой логический уровень; старые поля с номерами версий остались на своих местах, однако содержат значения, не относящиеся к TLS 1.3 (и, видимо, к следующим версиям). Со стороны клиента, в ClientHello, supported_versions включает список версий протокола, которые готов поддерживать клиент. Сервер передаёт в этом расширении номер выбранной версии. Данный механизм позволяет сохранить возможность использования предыдущих версий протокола. (Как описано выше, экспериментальные реализации TLS 1.3 при указании версии использовали специальный префикс 0x7F в supported_versions, это касается и сервера, и клиента.)

Сравним новую схему с TLS 1.2. Кроме уже упомянутого выше отсутствия сигнала ChangeCipherSpec, отсутствуют сообщения ClientKeyExchange, ServerKeyExchange и ServerHelloDone. При этом параметры, необходимые для построения криптографического контекста, из ClientKeyExchange и ServerKeyExchange перекочевали в расширения ClientHello и ServerHello: это key_share, supported_groups, а также signature_algorithms, psk_key_exchange_modes и pre_shared_key. В типичной ситуации, непосредственно для выработки криптографического контекста используются расширения supported_groups и key_share: первое содержит идентификаторы групп, используемых для протокола Диффи-Хеллмана; второе — открытый ключ или несколько открытых ключей (взятых в группах, перечисленных в supported_groups). Так как установление соединения TLS 1.3 проводится в защищённом режиме, расширения, содержащие криптографические параметры, необходимы. Более того, их наличие (вместе с supported_versions) — является необходимым признаком TLS 1.3. Криптографические операции TLS 1.3 рассмотрим подробно ниже, в специальном разделе.

Сообщение-сигнал ServerHelloDone (оно в предыдущих версиях имело нулевую длину и обозначало окончание первой партии серверных сообщений Handshake) заменено на серверное Finished.

Даже полный формат Handshake в 1.3 оказывается короче на одну итерацию: если взглянуть на предыдущую версию, то там, после получения ответа сервера (заканчивающегося ServerHelloDone), клиент должен был отправить свою порцию сообщений, завершающуюся Finished, и дождаться ответного серверного Finished, только после этого переходить к передаче полезной нагрузки. В новой версии — серверное сообщение Finished приходит в первом же ответе сервера, соответственно, клиент может сразу переходить к отправке полезной нагрузки (после своего Finished, конечно), не дожидаясь ещё одного пакета от сервера. Это экономит время, необходимое для доставки пакетов от клиента к серверу (и, вообще говоря, обратно). Такая же схема была предложена (и реализована) раньше под названием TLS False Start (RFC 7918), в версии 1.3 она, в доработанном виде, вошла в спецификацию самого протокола TLS. Для сервисов, устанавливающих тысячи TLS-соединений в секунду, уменьшение задержки в каждом сеансе на 30-100 мс, соответствующих времени передачи данных, очень существенно. Такая экономия ресурсов ускоряет работу сервиса для всех клиентов, а не только для поддерживающих TLS 1.3.

ClientHello 1.3

Среди нововведений версии 1.3 — запрет «пересогласования» соединения (renegotiation). Клиент больше не может отправить сообщение ClientHello внутри открытой TLS-сессии — это приведёт к прекращению сессии, так как является нарушением спецификации. Соответственно, отправка ClientHello возможна только при инициировании новой сессии. Зато на стороне сервера появилось сообщение HelloRetryRequest, которое может быть отправлено в сторону клиента и означает предложение повторного согласования сессии. При помощи HelloRetryRequest сервер может «мягко» сбрасывать несоответствующие требованиям запросы клиентов, ожидая, что в ответ клиент передаст скорректированное сообщение ClientHello.

Это новая для TLS концепция. В частности, HelloRetryRequest позволяет бороться с некоторыми видами активных атак при помощи сookie-сигнала, так как отправка cookie позволяет проверить, что клиент действительно отвечает по адресу, указанному в качестве адреса-источника запроса. Cookie в TLS 1.3 передаются в составе расширения HelloRetryRequest и имеют логическое сходство с известными куки-файлами в HTTP (или с менее известными cookie-сигналами из расширений TCP, где они используются для борьбы с SYN-флудом и другими видами флуда). Cookie представляет собой некоторый идентификатор (тикет), который сервер передаёт клиенту для того, чтобы клиент в следующем сообщении вернул данный тикет. Спецификация 1.3 предписывает использование конкретного cookie только в рамках одного TLS-соединения.

Схема согласования криптографического контекста в 1.3 делает шифронаборы, указываемые в ClientHello, несовместимыми с предыдущими версиями TLS. Однако клиент, готовый поддерживать предыдущие версии, может передавать в ClientHello и «новые», и «старые» варианты — формат идентификатора сохранился, это двухбайтовое значение. Понятно, что для установления соединения версии 1.3 — потребуется хотя бы один совместимый шифронабор.

Рекомендуемый список шифронаборов невелик: TLS_AES_128_GCM_SHA256, TLS_AES_256_GCM_SHA384, TLS_CHACHA20_POLY1305_SHA256, TLS_AES_128_CCM_SHA256, TLS_AES_128_CCM_8_SHA256. Здесь есть режим GCM, который широко используется с шифром AES. Есть режим CCM (Counter with CBC-MAC) — это режим счётчика (как и GCM), в котором аутентификация построена на коде CBC-MAC (разновидность кода аутентификации, по схеме построения совпадающая с режимом шифрования CBC). А также шифр ChaСha20, со схемой аутентификации Poly1305 (этот комплект криптопримитивов достаточно широко используется Google, например, он поддерживается браузером Chrome). Все упомянутые криптопримитивы достаточно давно используются в TLS на практике.

TLS 1.3 разрешает исключительно аутентифицированное шифрование, которое не требует использования дополнительной хеш-функции для вычисления кода аутентификации сообщения (в схемах аутентифицированного шифрования некоторый аналог хеш-функции встроен в саму схему). Тем не менее, хеш-функция требуется для вычисления сессионных симметричных ключей. Поэтому в шифронабор TLS 1.3 входит указание на тип хеш-функции: как видно из приведённого в предыдущем абзаце списка, это SHA-256 и SHA-384.

Таким образом, если устанавливается TLS-соединение без использования криптосистем подписи в целях аутентификации, то указание на такие криптосистемы вовсе не передаётся узлами. Соответственно, оказывается невозможным использование сертификатов для аутентификации узлов (в первую очередь, сервера). Если сертификаты используются, то необходимо указание совместимой с ними криптосистемы.

Перечень поддерживаемых криптосистем электронной подписи передаётся в обособленном расширении ClientHello — SignatureAlgorithms. Аналогичное по назначению расширение уже было введено в спецификации TLS 1.2, однако в TLS 1.2 объявляемые в составе ClientHello шифронаборы тоже содержат указание на криптосистему электронной подписи, то есть, присутствует некоторое дублирование. В 1.3 введено ещё одно расширение, уточняющее перечень схем подписи по отношению к сертификатам — это расширение SignatureAlgorithmsCerts, определяющее криптосистемы подписей в сертификатах. (Возможно использование только единственного расширения SignatureAlgorithms, которое является обязательным.)

Спецификация указывает несколько криптосистем: два варианта подписей, базирующихся на задаче RSA, широко распространённую ECDSA и новую криптосистему EdDSA, которая тоже работает на эллиптической кривой. RFC для последней опубликован в начале 2017 года. EdDSA — довольно прогрессивная криптосистема, построенная на задаче дискретного логарифмирования (схема подписи Шнорра, математически сходная с ECDSA) и работающая на эллиптических кривых в форме Эдвардса (откуда название). Кривые Эдвардса, при некоторых дополнительных условиях, оказываются очень эффективны при использовании в составе криптосистем электронной подписи. (Кривые Эдвардса также рекомендованы к использованию в российском стандарте электронной подписи ГОСТ Р 34.10-2012.)

Рассмотрим пример ClientHello TLS 1.3. Это сообщение браузера Chrome версии 68:

Смещение Байты Комментарий (десятичное) (шестнадцатеричная запись) 0000 16 ; Заголовок TLS-записи, тип - Handshake. 0001 03 01 ; Версия - используется значение 0x0301, то есть ; TLS 1.0, для TLS 1.3 - версия указывается в ; расширении SupportedVersions, а данное поле ; имеет только "историческое значение". 0003 02 00 ; Длина данных TLS-записи: 0x200 = 512 байтов, ; длина записи выравнивается под нужную границу при помощи ; байтов расширения Padding (см. ниже). Такое выравнивание ; не является необходимым. 0005 01 ; Тип сообщения - ClientHello. 0006 00 01 FC ; Длина данных сообщения: 0x1FC = 508 0009 03 03 ; Номер версии ("историческое значение": 0x0303 - TLS 1.2). 0011 16 3D 4D CB 35 ; Клиентское значение Random, 32 байта (полностью не приводится). [. ] 0043 20 ; Длина поля SessionID: 0x20 = 32 байта (типовая длина). 0044 93 13 EA E9 95 ; Значение поля SessionID, 32 байта (полностью не приводится). [. ] ; В TLS 1.3 SessionID может отсутствовать. Даже если данное поле ; используется, оно не служит указанием на номер сессии - его роль ; чисто сигнальная; в частности, сервер должен ответить ServerHello ; с тем же значением SessionID, которое было передано клиентом (это ; строгое требование). 0076 00 22 ; Длина списка шифронаборов: 0x22 = 34 байта, или 16 шифронаборов. 0078 8A 8A ; Начало списка. Первый элемент имеет значение 0x8A8A. Это так ; называемое Grease-значение - то есть, специальное значение, которое ; заведомо не поддерживается сервером. Передача таких значений ; браузером позволяет обнаружить серверы, работающие с ошибками, так ; как спецификация предписывает игнорировать неизвестные идентификаторы ; шифронаборов. Наличие Grease не регламентируется TLS, это особенность ; браузеров линейки Chrome/Chromium. Данные Grease имеют определённый ; формат. Так, в случае шифронаборов, оба байта должны иметь одинаковое ; значение, при этом младший "полубайт" равен 0xA. 0080 13 03 13 01 13 02 ; Три идентификатора шифронаборов, совместимых с TLS 1.3. А именно: ; 0x1303 = TLS_CHACHA20_POLY1305_SHA256; ; 0x1301 = TLS_AES_128_GCM_SHA256; ; 0x1302 = TLS_AES_256_GCM_SHA384. ; Шифронаборы клиент указывает в порядке предпочтения. 0086 CC A9 CC A8 C0 2B ; Далее следуют идентификаторы шифронаборов, совместимые с другими C0 2F C0 2C C0 30 ; версиями TLS. Их указание позволяет попытаться установить C0 13 C0 14 00 9C ; соединение TLS 1.2 c серверами, которые не поддерживают TLS 1.3. 00 9D 00 2F 00 35 ; Например, 0xCCA8 = TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256. 00 0A 0114 01 00 ; Строго зафиксированное значение, соответствующее длине и значению ; алгоритмов сжатия: в TLS 1.3 это поле может иметь только значение ; 0x01 (длина один байт), 0x00 - нуль (сжатие спецификацией ; не предусмотрено). ; Расширения (Extensions) ClientHello. Некоторые расширения строго ; необходимы - например, SupportedVersions. 0116 01 91 ; Длина блока расширений: 0x191 = 401 байт. 0118 2A 2A 00 00 ; Расширение Grease, аналогично Grease для шифронаборов. Данное расширение ; имеет нулевую длину (два байта со старшими адресами; первые два байта - ; это тип расширения: 0x2A2A). 0122 FF 01 ; Тип следующего расширения - 0xFF01, RenegotiationInfo. Это расширение ; не относится к TLS 1.3. (В более ранних версиях оно используется для ; повышения безопасности "пересогласования" TLS-соединения.) 00 01 ; Длина - один байт. 00 ; Значение: 0 (эта комбинация значений обозначает, что сессия ; только устанавливается; однако в TLS 1.3 расширение просто будет ; проигнорировано сервером). 0127 00 00 ; Расширение ServerName (тип 0x0000). Расширение содержит имя сервера, ; к которому производится обращение. (См. описание выше.) 00 10 ; Длина данных (0x10 = 16 байтов). 00 0E ; Длина элемента списка. 00 ; Тип записи (элемента списка). Значение 0 - символьное имя хоста. 00 0B ; Длина строки с именем (0x0B = 11 байтов) 74 6C 73 31 33 2E ; Значение имени, записанное в ASCII: в данном случае - tls13.1d.pw. 31 64 2E 70 77 0147 00 17 00 00 ; Два расширения (типы: 0x0017, 0x0023), имеющие нулевую длину. 00 23 00 00 ; Эти расширения не являются расширениями TLS 1.3. ; 0x0017 = ExtendedMasterSecret; ; 0x0023 = SessionTicket. 0155 00 0D ; Расширение с типом 0x000D. Это расширение TLS 1.3 SignatureAlgorithms. ; В расширении содержится перечень поддерживаемых криптосистем ; электронной подписи (этот перечень называется SignatureScheme). 00 14 ; Длина данных (0x14 = 20). 00 12 ; Длина элемента списка (перечня криптосистем). Далее идёт список ; двухбайтовых идентификаторов, каждый из которых обозначает криптосистему. ; Список (браузер передаёт идентификаторы в порядке предпочтения): 04 03 ; ecdsa_secp256r1_sha256; 08 04 ; rsa_pss_rsae_sha256; 04 01 ; rsa_pkcs1_sha256; 05 03 ; ecdsa_secp384r1_sha384; 08 05 ; rsa_pss_rsae_sha384; 05 01 ; rsa_pkcs1_sha384; 08 06 ; rsa_pss_rsae_sha512; 06 01 ; rsa_pkcs1_sha512; 02 01 ; rsa_pkcs1_sha1. 0179 00 05 ; Расширение 0x0005 StatusRequest, не является исключительным для TLS 1.3, ; оно используется и с другими версиями протокола. 00 05 ; Длина 5 байтов. 01 00 00 00 00 ; Это расширение позволяет клиенту запросить статус серверного сертификата. ; Под "статусом" подразумевается проверка того, не отозван ли сертификат. ; В данном случае запрашивается копия ответа респондера УЦ (OCSP), ; подтверждающего статус сертификата. Эту копию может вернуть сервер ; в составе расширений ServerHello. 0188 00 12 ; Расширение с типом 0x0012 - SignedCertificateTimestamp, тоже является ; расширением, используемым и в предыдущих версиях протокола. ; Это расширение позволяет привязывать серверные сертификаты к публичным ; реестрам (логам) сертификатов, работающих в рамках инициативы ; Certificate Transparency, рассмотрение которой находится за рамками ; данного описания. 00 00 ; Нулевая длина: расширение является сигналом браузера о поддержке ; технологии. 0192 00 10 ; 0x0010 - расширение ALPN (Application Layer Protocol Negotiation). ; Данное расширение предназначено для быстрого согласования протокола, ; который будет использоваться поверх TLS. 00 0E ; Длина данных (0x0E = 14 байтов). 00 0C ; Длина списка с идентификаторами. 02 ; Длина записи (первого) идентификатора, два байта. 68 32 ; Идентификатор протокола HTTP2, строка "h2". 08 ; Длина записи (второго) идентификатора, восемь байтов. 68 74 74 70 2F 31 2E 31 ; Идентификатор протокола HTTP/1.1, строка "http/1.1". 0210 75 50 ; Расширение с типом 0x7550 обычно называется Channel_ID и используется ; Google Chrome. Условно говоря, это "проприетарное" расширение TLS ; с временным типом, для которого пока нет RFC (только черновик, протокол ; называется Token Binding Protocol Negotiation). 00 00 ; У этого расширения нулевая длина данных. 0214 00 0B ; Расширение 0x000B - ECPointFormats. Это расширение определяет формат ; записи точек эллиптической кривой, который поддерживает клиент. ; Это расширение не является расширением TLS 1.3, но используется ; с версией 1.2 (см. выше). 00 02 ; Длина: два байта. 01 00 ; Значение: несжатый формат - 0x0100, единственно допустимый. 0220 00 33 ; Одно из важных расширений версии TLS 1.3. 0x0033 - KeyShare. ; Данное расширение содержит открытый параметр протокола DH клиента. ; Параметр необходим при установлении соединения, так как часть ответа сервера ; будет зашифрована, а генерация симметричных ключей базируется на протоколе ; Диффи-Хеллмана. 00 2B ; Длина данных. В расширении может быть перечислено несколько открытых ; ключей, каждый соответствует определённой группе, в которой работает DH. 00 29 ; Длина списка. В данном примере передаётся два параметра. 7A 7A ; Идентификатор группы первого параметра. Указано Grease-значение 0x7A7A. 00 01 ; Длина данных параметра (один байт - для Grease-значения это допустимо). 00 ; Сам "параметр" - нулевой байт. 00 1D ; Идентификатор группы второго параметра. 0x001D соответствует X25519. ; Эта криптосистема использует 32-байтовые ключи. 00 20 ; Длина данных ключа - 0x0020 = 32 байта. C4 EC ; Далее следует открытый параметр DH для X25519 (полностью не приводится). [. ] 0267 00 2D ; Расширение с типом 0x002D PSKKeyExchangeModes. Это раcширение TLS 1.3, ; управляющее тем, какие клиент и сервер используют режимы PSK, то есть, ; режимы установления (обычно - возобновления) соединения в условиях, ; когда уже есть дополнительный общий секрет (например, согласованный ; сторонами в предыдущей TLS-сессии). ; Режимы обозначаются однобайтовым кодом. В данном примере клиент передаёт ; единственный вариант. (Сервер данное расширение передавать не должен, это ; запрещено спецификацией.) 00 02 ; Длина данных. 01 ; Длина списка (один элемент). 01 ; Код режима: 01 - psk_dhe_ke (режим, включающий протокол Диффи-Хеллмана). 0273 00 2B ; Необходимое расширение TLS 1.3, которое и делает данное сообщение ; ClientHello - сообщением версии 1.3. 0x002B обозначает тип SupportedVersions, ; то есть, поддерживаемые версии. В TLS 1.3 список версий определяется строго ; этим расширением: все прочие указания на версии протокола - имеют лишь статус ; "исторических". 00 0B ; Длина данных (0x0B = 11 байтов). Данные расширения представляют собой список ; двухбайтовых идентификаторов версий. 0A ; Длина списка. 0A 0A ; Grease-значение версии. 7F 17 ; 0x7F17 - обозначает версию draft-23 TLS 1.3. То есть, это экспериментальная ; версия, использовавшаяся до того, как вышла спецификация. Более того, данная ; версия имеет существенные отличия от окончательной спецификации, и с TLS 1.3 ; в версии RFC несовместима. Окончательная версия TLS 1.3 имеет идентификатор ; 0x0304. ; Далее следуют прочие версии TLS, которые поддерживает браузер Chrome. 03 03 ; TLS 1.2 03 02 ; TLS 1.1 03 01 ; TLS 1.0 0288 00 0A ; Другое важное (и необходимое) расширение TLS 1.3 - SupportedGroups, тип 0x000A. ; В данном расширении клиент передаёт идентификаторы групп, которые он поддерживает ; в качестве основы протокола Диффи-Хеллмана. Список групп соответствует ; передаваемым открытым параметрам DH (см. расширение KeyShare). Однако групп может ; быть указано больше, чем передано ключей. Это означает, что сервер может ; инициировать новый раунд установления TLS-соединения, запросив DH конкретно ; в какой-либо из поддерживаемых групп. 00 0A ; Длина данных (0x0A = 10 байтов). 00 08 ; Длина списка (8 байтов). Далее идут идентификаторы групп, которые поддерживает ; браузер Chrome (это только группы точек эллиптических кривых). 7A 7A ; Grease-значение. 00 1D ; X25519 = 0x001D, открытый параметр DH X25519 передан в этом же ClientHello, ; в KeyShare; 00 17 ; Secp256r1 = 0x0017; 00 18 ; Secp384r1 = 0x0018. ; Как и в других похожих случаях, идентификаторы передаются в порядке предпочтения ; групп клиентом. 0301 4A 4A 00 01 00 ; Grease-расширение, имеющее длину в один байт. 0306 00 15 ; Специальное расширение с типом 0x0015 - Padding, которое предназначено для ; выравнивания длины ClientHello. Данные представляют собой нужное ; количество нулевых байтов. 00 D0 ; Длина расширения: 0x00D0 = 208 нулевых байтов, которые завершают сообщение. 00[. ]00

Итак, сервер может определить, что данное ClientHello является сообщением версии 1.3 по наличию необходимого расширения SupportedVersions. С другой стороны, сообщение выглядит как ClientHello предыдущей версии, TLS 1.2, с тем отличием, что содержит расширения, неизвестные для сервера, поддерживающего старую версию. Неизвестные расширения допускаются в TLS: клиент и сервер должны их игнорировать. Тем не менее, не следует делать вывод, что процедуры установления соединения (Handshake) в TLS 1.3 и TLS 1.2 совместимы — это не так. Формат ClientHello позволяет клиенту сразу же провести контролируемое понижение версии и выполнить установление соединения по схеме TLS 1.2, но если сервер поддерживает версию 1.3, то уже следующий шаг протокола будет радикально отличаться от 1.2 — и по составу сообщений, и по их структуре, а главное отличие состоит в моменте перехода на защищённый обмен данными.

Расширения ClientHello/ServerHello в TLS 1.3. Некоторые расширения, введённые в предыдущих версиях, сохранились и в 1.3, фактически, с теми же ролями. Как уже отмечено в пояснениях к примеру ClientHello, есть три важнейших расширения, которые и превращают сессию в сессию версии 1.3: SupportedVersions, SupportedGroups, KeyShare. Первое определяет версию протокола, второе и третье — необходимы для согласования криптографического контекста. Рассмотрим ряд других расширений (версии 1.3) подробнее.

PSKKeyExchangeModes и PreSharedKey. Эти расширения предназначены для создания сессий, использующих ранее распределённые между узлами (секретные) ключи. Определяют, соответственно, поддерживаемые режимы («прямой» режим, или режим с дополнительным использованием протокола DH) и идентификатор ключа. Очевидно, что секретный ключ не может передаваться в открытом виде, поэтому расширение PreSharedKey содержит только данные, позволяющие другой стороне найти нужный ключ у себя. Кроме того, PreSharedKey определяет срок действия ключа и ряд других параметров (криптосистему и пр.).

EarlyData. TLS 1.3 позволяет узлам возобновить соединение по максимально быстрой схеме, когда полезные данные передаются клиентом в первой же итерации. Например, клиент может сразу отправить HTTP-запрос GET. Сигналом, что клиент действует именно таким способом, служит наличие расширений EarlyData и PreSharedKey. Второе нужно для того, чтобы сервер мог выбрать ранее согласованный сторонами секрет и сгенерировать ключ, необходимый для расшифрования поступившего от клиента запроса — полезные данные всегда передаются в защищённом виде, то есть, внутри записей Application Data.

Cookie. Данное расширение, во-первых, позволяет серверу запросить у клиента подтверждение намерения установить соединение; во-вторых — позволяет оптимизировать управление сессиями на стороне сервера. Cookie может передаваться сервером вместе с HelloRetryRequest и содержит некоторую последовательность байтов, которую должен повторить клиент в своём следующем сообщении ClientHello (тоже в составе расширения Cookie). То есть, роль данного сообщения сходна со многими другими применениями различных «куки». Так, с его помощью сервер может существенно снизить затраты на обслуживание «зависших» сессий, — тем самым избежав ситуации отказа, — в случае одновременного открытия многих сессий злонамеренными узлами. В целом, так как TLS является протоколом уровня приложений и находится выше транспортного уровня, защита с помощью Cookie может оказаться не слишком эффективной. Например, в случае с TCP, если запросы от «завешивающих» сессию узлов доходят до TLS-сервера, это может означать, что где-то на более низких уровнях борьбы с атакой допущена ошибка. TCP-сессия существует независимо от TLS, поэтому, даже если серверу не требуется «держать» открытым состояние TLS-сессии, это не означает автоматически, что будет закрыта сессия TCP. Тем более, что занять сессию TCP атакующий мог ещё до того, как были переданы какие-либо данные уровня приложений. Тем не менее, ключевым отличием здесь является то, что объёмы вычислительных ресурсов, необходимых для обслуживания открытия TCP-сессии и TLS-сессии — несравнимы: TLS требует в тысячи раз больше (понятно, что TCP придётся обслуживать так или иначе). Соответственно, Cookie особенно полезны, когда используется безсессионый транспорт (например, UDP), так как в этом случае на транспортном уровне отсечь атаки с массовым открытием TLS-сессий невозможно (за отсутствием понятия сессии).

Кроме перечисленных выше расширений, в TLS 1.3 есть ряд других. Например, расширение CertificateAuthorities позволяет информировать другой узел о списке поддерживаемых доверенных удостоверяющих центров. Предусмотрено специальное расширение-сигнал для сервера о том, что клиент поддерживает аутентификацию клиента, а также ряд других расширений, которые мы не рассматриваем.

ServerHello 1.3

ServerHello — ответное сообщение сервера. На ClientHello сервер может ответить либо ServerHello, либо HelloRetryRequest. ServerHello в TLS 1.3 решает те же задачи, что и в версии 1.2, однако способ решения отличается. При помощи этого сообщения сервер выбирает шифронабор из предложенных клиентом, передаёт данные, необходимые для построения общего криптографического контекста. Так как в новой версии шифрование включается практически сразу, ServerHello обязательно содержит (в составе передаваемых расширений) параметры, позволяющие узлам незамедлительно получить общий секрет, который послужит прообразом симметричного ключа шифрования. Сервер вычисляет общий секрет сразу же, так как уже следующие за ServerHello сообщения должны передаваться в зашифрованном виде. Это важное, и весьма существенное, отличие от предыдущих версий TLS.

Как уже описано выше, в TLS 1.3 используются симметричные ключи нескольких уровней (или «этапов»). Ключи, применяемые для защиты сообщений Handshake, отличаются от ключей, используемых для защиты, собственно, трафика. Однако ключи следующих этапов — связаны с ключами этапов предыдущих. Вычисление каждого поколения использует дополнительные данные, поэтому только по секретным ключам Handshake восстановить ключи защиты трафика вычислительно сложно. Для определения общего секрета используется протокол Диффи-Хеллмана, клиентские параметры которого сервер уже получил в ClientHello. Источником дополнительных входных значений служат также сообщения Handshake, полученные и подготовленные к передаче сервером. Серверные параметры DH — передаются в составе ServerHello: в этом состоит ещё одно архитектурное отличие от предыдущих версий, в которых серверные DH-параметры передавались в специальном сообщении ServerKeyExchange (см. выше). Перенос параметров внутрь ServerHello, конечно, обусловлен тем, что использование протокола Диффи-Хеллмана стало обязательным.

С параметрами DH связан следующий момент: клиент может указать несколько вариантов поддерживаемых групп, но сами параметры передать не для всех из них. То есть, в терминах ClientHello, расширение SupportedGroups содержит больший перечень групп, чем перечень параметров в KeyShare. Это обычная ситуация в случае браузеров: как можно видеть в примере ClientHello Chrome выше — данный браузер передаёт только один (рабочий) параметр в KeyShare, это X25519, при этом список поддерживаемых групп SupportedGroups включает три элемента. Если сервер смог найти среди поддерживаемых групп те, которые совместимы с серверными настройками, но для этих групп клиент не передал параметров DH, то сервер может ответить вместо ServerHello сообщением HelloRetryRequest. Предполагается, что клиент, в таком случае, ответит новым ClientHello, передав параметры в нужной серверу группе. (Подобное использование HelloRetryRequest относится и к другим случаям, когда параметров в совместимом ClientHello серверу недостаточно для установления соединения.)

Основной особенностью сообщения HelloRetryRequest является то, что это сообщение по структуре полностью повторяет ServerHello, имеет такой же код типа. Отличить два сообщения клиент может только по значению поля Random. Это довольно интересная особенность TLS — использование значения Random в качестве сигнала. Есть и другая особенность: при наличии HelloRetryRequest — сервером используется другой механизм вычисления хеш-функции от переданных и принятых в рамках установления сессии сообщений. Схема отличается в одной детали, которая позволяет серверу «выгрузить» сохранение состояния на сторону клиента, при помощи расширения Cookie (которое, в данном случае, разрешается). Несомненно, это ещё один пример из ряда «неочевидных решений», используемых в TLS, тем не менее, его внедрение обусловлено заботой об оптимизации производительности протокола.

Рассмотрим пример сообщения HelloRetryRequest (а на следующем шаге — ServerHello TLS 1.3). Это сообщение, полученное от одного из серверов facebook.com; соответствующее ClientHello не содержало ни одного подходящего для сервера значения в списке ключей ClientKeyShare (заголовок TLS-записи не приводится):

Смещение Байты Комментарий (десятичное) (шестнадцатеричная запись) 0000 02 ; Тип сообщения: несмотря на то, что это сообщение HelloRetryRequest, ; указан тип 0x02, соответствующий ServerHello. 0001 00 00 54 ; Длина данных. 0x54 = 84 байта. 0004 03 03 ; Версия (историческое значение), 0x0303 = TLS 1.2. 0006 CF 21 AD 74 E5 9A 61 11 ; Поле Random. Так как это сообщение HelloRetryRequest, данное поле BE 1D 8C 02 1E 65 B8 91 ; содержит фиксированное значение, обозначающее тип сообщения. C2 A2 11 16 7A BB 8C 5E ; Значение приведено полностью, это 32 байта, значение SHA-256 07 9E 09 E2 C8 A8 33 9C ; от строки "HelloRetryRequest". 0038 20 ; Длина поля SessionID, 0x20 = 32 байта. 0039 10 20 30 ; Значение SessionID. Сервер возвращает копию значения, полученного [. ] ; в этом поле ClientHello (полностью не приводится). 0071 13 01 ; Идентификатор выбранного сервером шифронабора: ; 0x1301 = TLS_AES_128_GCM_SHA256. 0073 00 ; Историческое значение, обозначающее отсутствие сжатия. 0074 00 0C ; Длина блока расширений ServerHello. 0x0C = 12 байтов. 0076 00 2B ; Расширение 0x002B - SupportedVersions. Сервер передаёт значение версии ; протокола, которое было выбрано. 0078 00 02 03 04 ; Длина записи версии (два байта) и сама запись: 0x0304 = TLS 1.3. 0082 00 33 ; Расширение 0x0033 - KeyShare. Мы рассматриваем сообщение HelloRetryRequest, ; в этом сообщении, используя расширение KeyShare, сервер передаёт только ; идентификатор группы протокола Диффи-Хеллмана, для которой он ожидает ; получить клиентский ключ в новом ClientHello. 0084 00 02 00 1D ; Длина записи (два байта) и запись, обозначающая группу X25519 (0x001D).

Итак, HelloRetryRequest повторяет структуру ServerHello, но последнее, тем не менее, отличается по интерпретации клиентом. Перейдём к ServerHello TLS 1.3. Здесь приводится ServerHello, полученное от сервера Google, обслуживающего веб-сервис под доменом gmail.com. Соответствующее ClientHello содержало ключи для всех трёх «эллиптических вариантов» DH, сервером выбрана группа X25519. Разбор сообщения (заголовок TLS-записи не приводится):

Смещение Байты Комментарий (десятичное) (шестнадцатеричная запись) 0000 02 ; Тип - ServerHello = 0x02. 0001 00 00 76 ; Длина данных: 0x000076 = 118 байтов. 0004 03 03 ; Историческая версия (актуальная - передаётся в расширении SupportedVersions). ; 0x0303 = TLS 1.2. 0006 CD F3 1F DD 1B 59 A5 E5 ; 32 байта Random (полностью не приводится). ; Это байты со случайными значениями, так как в ServerHello роль данного поля ; состоит именно в передаче серверной части случайного набора данных, который ; позже войдёт в состав основы сеансовых ключей. [. ] 0038 20 ; Длина данных SessionID, 0x20 = 32 байта. ; Как описано выше, SessionID здесь служит только для передачи значения, ; полученного в ClientHello. 0039 DE AD DE ; 32 байта значения SessionID, полностью не приводятся. [. ] 0071 13 01 ; Идентификатор выбранного сервером шифронабора: ; 0x1301 = TLS_AES_128_GCM_SHA256. 0073 00 ; Фиксированное нулевое значение, один байт: нет сжатия. 0074 00 2E ; Длина расширений ServerHello. 0x2E = 46 байтов. 0076 00 33 ; Расширение 0x0033 = KeyShare. В этом расширении сервер передаёт открытый ; серверный ключ протокола Диффи-Хеллмана в выбранной группе. 0078 00 24 ; Длина данных расширения, 0x24 = 36 байтов. 0080 00 1D ; Идентификатор используемой группы: 0x001D - это X25519. 0082 00 20 ; Длина записи ключа. Для X25519 запись ключа требует 32 байта (0x20). ; Значение ключа передаётся в следующем поле. Криптосистема X25519 ; работает в группе точек эллиптической кривой, однако отличается ; от других эллиптических вариантов DH, в том числе, от описанного выше ; "прямого" алгоритма. Ключ X25519 порождается на основе одной из координат ; точки кривой, но для придания ключам некоторой специальной формы, снижающей ; вероятность ошибки, дополнительно трансформируется. Впрочем, для простоты ; можно считать, что это одна 32-байтовая (256-битная) координата. 0084 38 9B E0 44 ; 32 байта ключа X25519. [. ] 0116 00 2B ; Расширение SupportedVersions = 0x002B. 0118 00 02 03 04 ; Длина (два байта) и значение: 0x0304 = TLS 1.3. ; Клиент мог предложить несколько поддерживаемых версий, в том числе, несколько ; draft-версий TLS 1.3. Сервер передаёт единственный номер, соответствующий ; выбранной версии. В случае, если бы сервер (теоретически) выбрал версию ниже ; TLS 1.3 (при условии наличия такой в предложенном клиентом списке), то данное ; расширение не использовалось бы. На практике, сервер, поддерживающий TLS 1.3, ; встретив совместимое ClientHello, должен пытаться согласовать именно 1.3.

Попробуем поместить ServerHello версии 1.3 и ServerHello предыдущих версий в единый логический контекст, чтобы выявить основные различия. Сразу же можно заметить, что в версии 1.3 клиент предлагает серверу возможные параметры DH. В предыдущих версиях — инициатива была за сервером, клиент мог только ответить сообщением ClientKeyExchange. Благодаря изменению ролей, узлы уже после передачи ServerHello получают общий секрет. Надо отметить, что в TLS 1.3 клиент также может переложить задачу выбора параметров алгоритма Диффи-Хеллмана на сервер, для этого служит описанный выше механизм HelloRetryRequest: клиент просто передаёт пустой список групп, а в ответ получает рекомендацию сервера. Естественно, это обходится в дополнительную итерацию. Передача случайных значений Random, списков шифронаборов — тут сохраняется логика предыдущих версий. В предыдущих версиях присутствовали и расширения, однако в 1.3 роль их стала значительно важнее, хотя бы потому, что именно наличие определённых расширений (SupportedVersions и др.) делает ServerHello сообщением версии 1.3.

Защищённые сообщения Handshake в TLS 1.3

ServerHello, при штатном ходе установления соединения, является единственным сообщением сервера, которое передаётся в открытом виде. Уже следующее сообщение — EncryptedExtensions — зашифровано. Зашифрованные сообщения в TLS 1.3 передаются строго внутри TLS-записей с типом Application Data (0x17). Это ещё одно важное отличие от предыдущих версий. Мы подробно рассмотрим формат защищённых записей ниже, в специальном подразделе, а сейчас отметим только один момент: «настоящий» тип записи — Handshake (0x16) — передаётся внутри защищённой записи, и доступен только после того, как эта запись успешно расшифрована.

Используя общий секрет, полученный в рамках обмена Диффи-Хеллмана, а также все переданные к настоящему моменту сообщения, узлы определяют текущие симметричные ключи. Предположим, что сервер выбрал шифронабор TLS_AES_128_GCM_SHA256 (0x1301). Тогда, для успешной защиты сообщений, потребуется пара симметричных ключей: будем обозначать их как sh_write, sh_read (от Server Handshake Write/Read). Длина этих ключей — 128 бит, соответствует разрядности ключей шифра. Обозначения write и read нужны потому, что один ключ используется для записи сообщений в канал, то есть, для отправки их в сторону клиента, а второй — для чтения. На стороне клиента — ключи меняются местами. Схема полностью аналогична описанной выше. Кроме ключей, узлы должны определить векторы инициализации шифров, это начальные значения, необходимые для работы шифра в режиме аутентифицированного шифрования.

Сам алгоритм вычисления ключей и векторов инициализации в TLS 1.3 отличается от предыдущих версий. Для получения нужной «порции битов» используется функция, которая в спецификации называется HKDF-Expand-Label:

Для ключа: key = HKDF-Expand-Label(Secret, "key", "", key_length) Для вектора инициализации (iv): write_iv = HKDF-Expand-Label(Secret, "iv", "", iv_length)

Функция возвращает нужное количество битов ключа или вектора инициализации — длины их, соответственно, передаются в key_length и iv_length. Рассмотрим другие аргументы:

Secret - это секрет, соответствующий текущему этапу протокола, он, например, отличается для установления соединения и для этапа обмена полезными данными; "key"/"iv" - текстовые строки, обозначающие предназначение ключевой информации. Строки вводятся для того, чтобы результаты дополнительно различались, а разработчики, реализующие протокол, имели меньше шансов на ошибку. Подобные текстовые строки используются в TLS 1.3 и во всех других случаях генерации ключей.

Функция HKDF-Expand-Label устроена несколько сложнее, чем может показаться: внутри скрываются другие функции, которые ставят генерируемую информацию в соответствие с текущим контекстом. То есть, симметричные ключи в TLS 1.3 зависят от множества факторов.

Вернёмся к процессу установления соединения. Следом за ServerHello сервер обязательно передаёт сообщение EncryptedExtensions. Это логический блок, в который помещаются те расширения ServerHello, которые спецификация позволяет передавать в зашифрованном виде. Нередко сообщение EncryptedExtensions не содержит ни одного расширения, однако в таком случае необходимо передать пустое сообщение (то есть, состоящее только из заголовка).

Примеры EncryptedExtensions (обратите внимание, что здесь, по очевидным причинам, приводится расшифрованное сообщение; в реальных сессиях — это сообщение передаётся в защищённой TLS-записи с «историческим» типом 0x17; такой тип используется потому, что в TLS 1.3 он назначается всем защищённым записям, а подлинный тип записи — содержится внутри защищённых данных):

Смещение Байты Комментарий (десятичное) (шестнадцатеричная запись) (Пустое сообщение EncryptedExtensions.) 0000 08 ; Тип сообщения: 0x08 = EncryptedExtensions. 0001 00 00 02 ; Длина: 2 байта. 0004 00 00 ; Пустая строка (строка нулевой длины, то есть только два байта, ; обозначающих нулевую длину).
Смещение Байты Комментарий (десятичное) (шестнадцатеричная запись) (Cообщение EncryptedExtensions, содержащее два расширения.) 0000 08 ; Тип сообщения: 0x08 = EncryptedExtensions. 0001 00 00 16 ; Длина данных: 0x16 = 22 байта. 0004 00 14 ; Длина списка расширений: 0x14 = 20 байтов. 0006 00 00 ; Тип расширения: 0x0000 = ServerName (передано пустое расширение). 0008 00 00 0010 00 0A ; Тип расширения: 0x000A = SupportedGroups. Это расширение содержит ; перечень групп, поддерживаемых сервером (см. описание выше, ; в ClientHello). 0012 00 0C ; Длина данных (0x0C = 12 байтов). 0014 00 0A ; Длина списка (0x0A = 10 байтов). 0016 00 1D 00 17 00 1E ; Перечень идентификаторов групп. 00 19 00 18

За EncryptedExtensions может последовать либо сообщение CertificateRequest (запрос сертификата клиента), либо Certificate — последнее содержит серверный TLS-сертификат. За исключением того, что эти сообщения зашифрованы, они аналогичны соответствующим сообщениям в предыдущих версиях. Передача Certificate сервером требует передачи и сообщения CertificateVerify.

В сообщении ClientHello клиент передаёт расширение SignatureAlgorithms, содержащее список поддерживаемых криптосистем электронной подписи. Одна из этих криптосистем используется сервером для вычисления значения CertificateVerify — сообщения, решающего сразу две важных задачи: во-первых, это сообщение позволяет клиенту проверить, что у сервера действительно есть секретный ключ от представленного сертификата; во-вторых, оно удостоверяет содержание полученных к этому моменту на стороне сервера других сообщений Handshake (перечень и содержание отправленных клиентом сообщений клиент знает и так). Очевидно, что список поддерживаемых криптосистем подписи должен включать криптосистему, совместимую с сертификатом, так как вычисление подписи не от ключа сертификата — не имеет никакого смысла. То есть, CertificateVerify прежде всего следует рассматривать как основополагающую часть механизма аутентификации сервера клиентом. TLS-сертификат является публичным электронным документом, поэтому всякий может скопировать серверный сертификат и, позже, передавать его подключающимся клиентам. Однако наличие актуальной подписи лишает такой ход смысла.

Подпись CertificateVerify вычисляется от всего набора полученных (к моменту вычисления) сервером сообщений — откуда и возникает инструмент раннего удостоверения подлинности сессии: если между клиентом и сервером находится активный атакующий, который модифицирует сообщения, то клиент обнаружит расхождение подписи, так как проверяет её для своей копии переданных сообщений. Это существенное улучшение ситуации, по сравнению с предыдущими версиями протокола, в которых подобное удостоверение подлинности становилось возможным только в самом конце, после получения сообщения Finished.

В предыдущих версиях TLS аналогичное по значению сообщение передавал только клиент, в случае своей аутентификации сервером. В отношении же самого сервера, в зависимости от используемой схемы генерации общего секрета, предполагалось, что только узел, располагающий секретным ключом, сможет расшифровать переданные клиентом данные, либо о наличии секретного ключа можно судить по подписи на сообщении ServerKeyExchange. При этом, подпись на ServerKeyExchange не защищает прочие сообщения Handshake. (В TLS 1.3 сообщения ServerKeyExchange нет вообще.)

Сообщение CertificateVerify имеет очевидную структуру: оно состоит из идентификатора криптосистемы подписи и самой подписи. Важнее посмотреть на то, как именно, и какие данные подписываются. Электронная подпись на практике вычисляется для значения хеш-функции от подписываемого блока данных. В случае CertificateVerify исходными данными служат все сообщения, полученные и переданные сервером к моменту генерирования подписи, а именно: сообщения, начиная от ClientHello и до, включительно, EncryptedExtensions или CertificateRequest; плюс — в цепочку добавляется сообщение Certificate. Обратите внимание, что в цепочку сообщений входят и HelloRetryRequest, если оно отправлялось сервером, и первое ClientHello. От объединения сообщений вычисляется значение хеш-функции, которое помещается в специальную структуру, и уже эта структура поступает на вход криптосистемы электронной подписи.

Клиент проверяет подпись CertificateVerify при помощи открытого ключа, содержащегося в серверном сертификате — этот ключ известен из сообщения Certificate.

Завершает набор серверных сообщений — серверное Finished. Это сообщение, как и в TLS предыдущих версий, содержит отпечаток всех известных серверу сообщений Handshake, которые предшествовали Finished. Finished является HMAC (кодом аутентификации с хеш-функцией), использующей секретный ключ. Этот ключ, в свою очередь, стороны вычисляют на основе имеющегося у них секрета. Обратите внимание, что Finished передаётся в зашифрованной TLS-записи и уже защищено кодом аутентификации используемого режима шифрования. Именно в таком режиме передаётся и Finished предыдущих версий протокола (см. выше). То есть, здесь логика хорошо совпадает, за исключением того, что в TLS 1.3 серверное Finished передаётся на шаг раньше.

В TLS 1.3 исключены сообщения-сигналы ChangeCipherSpec (CCS), которые в более ранних версиях обозначали момент перехода в защищённый режим обмена данными. Однако экспериментальное внедрение TLS 1.3 ещё на ранних стадиях (речь про draft-версии) показало, что в ряде случаев TLS-соединение без CCS распознаётся разными системами инспекции трафика (DPI) как подозрительное (или «некорректное»), и, соответственно, разрывается. К сожалению, использование подобных «практик», а также оборудования DPI (и DLP), спроектированного с ошибками, является нормой для корпоративных сетевых сред, поэтому в TLS пришлось внести соответствующие дополнения: сигнал CCS вернулся в качестве фиктивного сообщения, которое никак не учитывается узлами, но позволяет «обмануть» DPI, делая соединение возможным.

Клиентская часть сообщений Handshake так же завершается Finished. После того, как стороны проверили Finished и убедились, что значения корректны, сессия считается установленной, а узлы переходят на новое поколение ключей.

Управление сеансовыми ключами в TLS 1.3

В TLS 1.3 используется многоэтапный подход к управлению симметричными ключами. Его логика строится на следующих предложениях: 1) каждая фаза протокола должна использовать свой набор ключей; 2) значения ключей должны зависеть не только от общего секрета и параметров Random, но и от других свойств конкретной сессии; 3) каждый следующий набор ключей зависит от предыдущего и дополнительной информации.

Основу для общего секрета составляет значение, полученное в рамках обмена DH, также (в дополнение к DH) может использоваться секретное значение, которое узлы согласовали каким-то способом ранее (схемы PSK). Поколения ключей соответствуют ходу соединения, при этом вычисление каждого поколения ключей основано на соответствующем поколении общего секрета. Схема не очень сложная, представляет собой ступенчатый переход от секрета к секрету, с подмешиванием новой информации на каждом шаге. Подмешиваемая информация представляет собой текстовые строки и сообщения протокола, которые преобразуются при помощи специальной функции. Тем не менее, в предыдущих версиях TLS ничего похожего не было. Однако механизм не является сколь-нибудь уникальным или особенным: есть немало криптографических протоколов, где применяется сходный подход, в качестве примера куда более сложного развития этой же идеи можно привести протокол Signal, который, как утверждается в документации, использует мессенджер WhatsApp (и ряд других приложений).

Рассмотрим упрощённую схему генерации ключей. Этапы идут сверху вниз, начиная от «пустого» значения, обозначенного 0 (в протоколе это строка нулевых байтов заданной длины). Центральная вертикальная линия соответствует движению ключевого материала, где к нему последовательно применяется функция генерации ключей (HKDF). Cлева — показаны основные источники входных данных с ключевой информацией. Справа — промежуточные результаты (общие секреты), сообщения Handshake, используемые в качестве дополнительно подмешиваемой информации, и симметричные «этапные» секреты, которые получаются на каждом шаге. Подмешивание информации происходит через последовательное вычисление значений хеш-функций и объединения (конкатенации) входных сообщений. Пример: если на входе имеется пара сообщений (ClientHello, ServerHello), а текущий этап является этапом Handshake (II — на схеме; указан Handshake Secret), то байты сообщений, в том порядке, как они передавались на транспортном уровне, объединяются в одну строку, от этой строки вычисляется хеш-функция, к результату присоединяется строка символов «c hs traffic», которая обозначает этап, а получившийся новый набор байтов, вместе с общим секретом, служит аргументом для генерации набора ключей при помощи функции Derive-Secret(). В реальном протоколе отличаются некоторые детали, в частности, используются специальные «обёртки» вокруг хеш-функций, но алгоритмическая логика — точно такая, как описано.

0 | v PSK -> HKDF = Early Secret ; Самый ранний этап. Здесь используется общий секрет, | ; возможно, полученный до установления соединения (PSK). +-----> [ClientHello] ; При отсутствии такого секрета - используется пустая | | ; строка. I) | v ; ClientHello - служит дополнительной информацией, | binder_key, ; получаются наборы секретов binder_key и т.д. | client_early_traffic_secret, | early_exporter_master_secret. | v Derive-Secret(., "derived", "") ; Переход между этапами сопровождается трансформацией секрета. | v (EC)DHE -> HKDF = Handshake Secret ; Следующий этап - Handshake. Здесь в качестве источника | ; ключевой информации служит общий секрет, полученный +-----> [ClientHello. ServerHello] ; при помощи протокола DH (слева). Дополнительная информация | | ; это сообщения ClientHello, ServerHello. В результате - II) | v ; получаются наборы секретов для защиты сообщений на этапе | client_handshake_traffic_secret, ; Handshake. | server_handshake_traffic_secret. | v Derive-Secret(., "derived", "") | v 0 -> HKDF = Master Secret | +-----> [ClientHello. server, client Finished] ; Первый набор ключей для защиты полезного трафика приложений | | ; получается по той же схеме, но в качестве дополнительной | v ; информации служат сообщения от ClientHello до серверного III) | client_application_traffic_secret_0, ; Finished. (Для resumption_master_secret - до клиентского | server_application_traffic_secret_0, ; Finished, так как данный секрет предназначен для будущих | exporter_master_secret, ; сессий.) | resumption_master_secret. . . . Упрощённая схема преобразования ключей в TLS 1.3. (RFC 8446)

Обратите внимание, что на схеме отражён алгоритм генерации симметричных секретов, но это ещё не сами сеансовые ключи. Ключи, а также соответствующие векторы инициализации, получаются на основе этих секретов в результате применения функции из семейства HKDF, а именно — HKDF-Expand-Label(). Узлы могут периодически заменять ключи защиты трафика приложений, выполняя ещё одну итерацию преобразования (этап III).

Сокращённый вариант установления соединения (Handshake) в TLS 1.3

При проектировании TLS 1.3 большое внимание уделялось снижению потерь времени в работе протокола. Основной вклад в задержку по времени вносит установление соединения. Поэтому предусмотрена сокращённая схема, которая оказывается даже быстрее сокращённой схемы предыдущих версий. Новая схема носит условное название 0-RTT (Zero Round-Trip Time — нулевая задержка приёма-передачи).

Для использования данной схемы требуется, чтобы стороны заранее согласовали общий секрет (как описано выше). Если такой секрет известен, то клиент может начать соединение отправкой ClientHello, с указанием общего секрета, за которым сразу же следуют данные полезной нагрузки. В случае с HTTPS, такими данными будет, например, запрос HTTP GET — так как это самый распространённый сценарий в работе веб-сервисов. Другими словами, клиент сразу же, не дожидаясь ответа сервера, приступает к отправке запросов уровня приложения. В случае, если сервер успешно принял соединение, он отвечает сообщением ServerHello и другими сообщениями (Certificate и т.д.), заключает фазу открытия сессии сообщением Finished, и сразу же отправляет полезные данные, являющиеся ответом на запрос приложения клиента. В случае HTTPS, это будет HTTP-ответ на клиентский GET-запрос. Несложно заметить, что схема, по задержкам приёма-передачи, полностью эквивалентна обычной схеме HTTP: клиент отправляет запрос и получает ответ на него. При этом часть, относящуюся к TLS, можно считать некоторой дополнительной «обёрткой» над HTTP-схемой, не требующей выделенных сеансов приёма-передачи.

Клиентский запрос в схеме 0-RTT не обладает прогрессивной секретностью: он зашифрован не c выделенным сеансовым ключом, а c общим секретным ключом, полученным в другом сеансе, кторый должен был быть где-то сохранён. Соответственно, если ключ будет скомпрометирован, получившая его сторона сможет расшифровать клиентскую часть Handshake из записанного ранее трафика. Этот аспект 0-RTT относится только к клиентскому запросу, так как дальнейший трафик приложения защищается с использованием сессионных ключей, которые уже могут быть сгенерированы с обеспечением прогрессивной секретности. По этой и ряду других причин, схема 0-RTT в целом считается менее безопасной (это отмечено в спецификации TLS 1.3).

Защита данных расширения SNI

Расширение SNI (Server Name Indication) используется для передачи серверу логического имени ресурса, с которым планирует установить соединение клиент. Как видно из разобранных выше сообщений — SNI содержит строку символов, в которой имя записано. Эта строка передаётся в открытом виде, но при этом является одним из важнейших элементов, несущих метаинформацию о соединении. SNI оказывается необходимым в конфигурации, когда один и тот же IP-адрес разделяется несколькими ресурсами под несколькими именами хостов (например: cp.example.com, web.example.com и т.д. — все размещаются на IP-адресе 10.1.2.3), но для каждого имени используется свой TLS-сертификат и разные серверные ключи. Сервер должен отправить клиенту серверный сертификат в самом начале соединения. Если таких сертификатов несколько и они различаются по именам, то, в случае простого ClientHello, без указания SNI, сервер не может определить, какой сертификат отправить. При этом процесс валидации сертификата клиентом требует, чтобы имя узла, которое ожидает получить клиент, совпало с именем в сертификате. (Оговорка про IP-адрес здесь важна потому, что если узел использует один IP-адрес для одного имени, то определить подходящий сертификат на стороне сервера можно по IP-адресу, с которым соединился клиент.)

SNI поддерживается всеми современными браузерами и повсеместно используется в вебе. Это означает, что на начальном этапе установления соединения клиент раскрывает третьей стороне, пассивно прослушивающей трафик, имя узла, с которым пытается соединиться. Получается, что полезный трафик защищён TLS, но прослушивающей стороне видны имена, к которым обращается клиент. Это хорошо известная особенность. Попытки побороть данную утечку предпринимались довольно давно, а особенно активно — в ходе разработки версии TLS 1.3. Однако ввести защиту SNI от прослушивания непосредственно в спецификацию TLS 1.3 не получилось. Это, в основном, связано с тем, что всякая защита SNI требует дополнительных вычислительных затрат: имя в SNI нужно для того, чтобы найти подходящий сертификат на стороне сервера; этот сертификат содержит ключ, необходимый для создания защищённого канала, поэтому защитить SNI тем же ключом — не получится; это означает, что нужны дополнительные ключи, которые требуют согласования и, следовательно, обмена сообщениями. Другими словами, сложно выстроить простую и надёжную схему. Тем не менее, экспериментальный механизм защиты SNI для TLS 1.3 всё же появился в 2019 году. На стороне клиента поддержку добавили в браузер Firefox. По результатам экспериментов, после длительных обсуждений, первоначально предложенный вариант фактически забраковали и полностью переделали, но и новая спецификация всё ещё далека от повсеместного, практического внедрения (2023).

Изначально механизм назывался ESNI (Encrypted SNI), однако позже, по мере развития спецификации и появления новых особенностей, название изменили на ECH (Encrypted ClientHello), под которым технология и известна сейчас (2023). Спецификация ECH всё ещё находится в состоянии черновика. Старое название (ESNI) показывает, что защищать планировали именно и только поле SNI. Новое название наводит на мысли о том, что здесь уже прячется полноценное сообщение ClientHello. Именно так и обстоит дело. В ESNI предполагали передавать зашифрованное имя сервера (SNI) в специальном расширении сообщения ClientHello. Новый вариант технологии отличается концептуально, поскольку построен на полноценном туннелировании TLS-соединения. Это достигается при помощи инкапсуляции секретного (внутреннего) сообщения ClientHello2 в открытое (внешнее) сообщение ClientHello1. Естественно, так как сведения об имени скрытого ресурса передаются во внутреннем ClientHello2, то схема полностью решает и задачу сокрытия SNI. Однако ECH предоставляет гораздо более высокий уровень секретности: технология позволяет клиенту защитить сам процесс установления TLS-соединения со скрытым сервисом. Обратите внимание, что изначально TLS не пытается скрывать факт установления соединения между двумя узлами. ECH, на первый взгляд, укладывается в эту концепцию, поскольку защищённое ClientHello2 хоть и зашифровано, но сам факт его передачи в составе внешнего соединения не скрывается. При ближайшем же рассмотрении оказывается, что факт наличия защищённого ClientHello2 является свойством внешнего TLS-соединения, которое лишь выступает в роли средства прикрытия и полноценным TLS-соединением не является. Этот аспект особенно рельефно виден, если учитывать, что скрытый сервис может иметь другой IP-адрес, а тот узел, к которому обратился клиент с начальным сообщением ClientHello1, только туннелирует внутреннее TLS-соединение, содержание которого недоступно для просмотра, в том числе, и на проксирующем узле. Таким образом, ECH — это шаг в сторону реализации стеганографического подхода к созданию TLS-соединений.

Для установления соединения с защищённым сообщением ClientHello сторонам требуется согласовать секрет, который позволит сгенерировать общий симметричный ключ. В качестве основного транспорта для публикации ключей используется доменная система имён (DNS). DNS здесь работает следующим образом: в специальной DNS-записи, связанной с точкой входа скрытых сервисов, публикуется набор криптографических параметров (в том числе, открытых ключей), которые поддерживает скрытый сервер. Клиент, — это может быть браузер, — извлекает из DNS ключи, вычисляет секрет и, на основе этого секрета, симметричный ключ, который используется при зашифровании дополнительного сообщения ClientHello. Зашифрованные таким образом данные клиент передаёт серверу в составе начального сообщения ClientHello, внутри специального расширения. То есть, полезная нагрузка ECH — передаётся в формате расширения ClientHello. Сервер, располагая соответствующими секретными ключами, может вычислить симметричный ключ и расшифровать внутреннее сообщение ClientHello (ClientHello2). После того, как определены параметры скрытого ClientHello2, туннелирующий узел передаёт это сообщение скрытому сервису, который выполняет оставшиеся шаги алгоритма начального установления TLS-соединения. При этом туннелирующий узел лишь обеспечивает обмен данными между клиентом и скрытым сервисом.

Фактически, за вычетом некоторых логических отличий, можно считать, что клиент устанавливает со скрытым сервисом TLS-соединение через туннель, обеспечиваемый внешним, входным узлом. Важно понимать, что при этом никакого внешнего TLS-соединения не существует, оно лишь имитируется на начальном этапе. Туннелирование осуществляется на транспортном уровне (входной узел просто копирует пакеты в обе стороны, никак их не изменяя), а полезная нагрузка соединения зашифровывается с теми ключами, которые клиент согласовал непосредственно со скрытым сервисом. Тем не менее, так как используется TLS 1.3, в котором уже начальная фаза установления соединения защищена от прослушивания, а также из-за семантических свойств зашифрованных данных, для третьей стороны скрытое TLS-соединение не отличается от «обычного». Подлинное имя сервера оказывается защищено от просмотра третьей стороной, а необходимые дополнительные ключи — публикуются в DNS, то есть, логически не зависят от транспорта конкретной TLS-сессии.

В подобных схемах открытая часть сообщений клиента может содержать маскирующее имя сервера (эта идея высказывалась в черновике Fake SNI), либо не содержать имени сервера вообще. Естественно, запрос к DNS, необходимый для получения ключей, может послужить каналом утечки, аналогичным открытому полю SNI. Предполагается, что, во-первых, клиент использует защищённый способ доступа к DNS (например, DNS-over-TLS); во-вторых, для дополнительной маскировки ключи могут публиковаться под DNS-именем, которое отличается от скрытого имени сервера (естественно, такое «имя прикрытия» должно быть заранее известно клиенту); в-третьих, ключи вообще могут быть распределены способом, отличным от DNS, например, непосредственно в составе дистрибутива браузера (или другой программы-клиента).

Черновик RFC ECH предусматривает выделение для хранения ключей отдельного типа DNS-записи. Кроме ключей и других криптографических параметров, соответствующая DNS-запись сможет включать и IP-адреса сервера. Это означает, что клиенту достаточно будет одного запроса в DNS для извлечения и ключей, и адреса сервера.

Асимметричные криптосистемы, электронная подпись

Для организации защищённого соединения в TLS используются асимметричные криптосистемы, криптосистемы электронной подписи. На практике сейчас это RSA и ECDSA. Как описано выше, RSA может применяться в исторической схеме для передачи сеансового секрета клиентом на сервер (такая схема всё ещё встречается). ECDSA — служит только для получения подписи, то есть, аутентификации. Предполагается, что в ближайшем будущем RSA окажется вытеснена эллиптическими системами, а в качестве второго направления добавятся постквантовые алгоритмы (то есть, криптосистемы, обладающие стойкостью в предположении атаки на квантовом компьютере).

Криптосистема RSA

RSA — самая массовая криптосистема с открытым ключом (асимметричная криптосистема). Повсеместно используется для подписи в составе TLS-сертификатов. Долгое время RSA являлась, фактически, единственной криптосистемой TLS-сертификатов. Лишь в 2014 году наряду с RSA в сертификатах стала заметна доля ECDSA. Логика построения RSA напоминает протокол Диффи-Хеллмана, однако отличаются свойства однонаправленной функции. В RSA однонаправленная функция имеет «лазейку» или «чёрный ход», знание которого позволяет легко обратить функцию, вычислить аргумент по значению. RSA основана на возведении в степень по модулю (то есть, «взятие остатка»), а стойкость этой криптосистемы связана с задачей разложения числа на простые множители. Можно считать, что секретом в RSA является именно разложение «ключа» на простые множители. Слово «ключ» здесь дано в кавычках, так как на практике ключ содержит дополнительный параметр, но этот параметр всегда можно легко вычислить, зная разложение. (Задачу разложения числа на простые множители принято называть «задачей факторизации».)

Параметрами криптосистемы RSA являются модуль (это всегда составное число) и открытая (часто её называют «шифрующей») экспонента — то есть, показатель степени, в которую возводится числовое значение сообщения. Сообщение, в рамках RSA, это целое число, записываемое в виде последовательности байтов. Модуль в RSA является составным числом: N = pq, где p и q — достаточно большие простые числа, именно их и нужно держать в секрете. (Строго говоря, успехи криптоанализа RSA накладывают на p и q немало дополнительных требований, которые мы не рассматриваем, так как для понимания принципа работы криптосистемы это не важно.) Знание разложения N = pq позволяет построить «лазейку», с помощью которой можно обратить однонаправленную функцию, лежащую в основе RSA. «Лазейка» состоит в том, что для шифрующей экспоненты вычисляется обратный элемент — расшифровывающая экспонента. Быстро вычислить обратный элемент позволяет знание разложения модуля ключа на простые множители.

Итак, помимо модуля, для использования RSA с целью генерирования электронной подписи и расшифрования сообщений, необходимо сгенерировать секретный ключ. Секретным ключом как раз и является экспонента, обратная к шифрующей (расшифровывающая). В случае TLS, сервер публикует модуль N и шифрующую экспоненту e, а в секрете сохраняется соответствующая e расшифровывающая экспонента d = e -1 по модулю (p-1)(q-1) (нередко в состав представления секретного ключа входит и разложение модуля — числа p и q; это позволяет ускорить вычислительные операции; конечно, зная открытую и секретную экспоненты — несложно факторизовать и модуль, но данная операция потребует дополнительных затрат). Таким образом, открытый ключ состоит из модуля N и экспоненты e, а закрытый — из N,p,q,d — модуля, разложения модуля (p,q) и секретной экспоненты. Так как шифрующая экспонента это публичный параметр, то повсеместно используются типовые значения, например, 65537 (или 0x010001). При этом соответствующая секретная (расшифровывающая) экспонента будет отличаться для разных значений модуля N. Открытый ключ обычно публикуется в составе сертификата TLS (сертификаты подробнее рассмотрены в специальном разделе) и служит для проверки подписей, а для их вычисления — необходимо знать соответствующий секретный ключ.

RSA позволяет зашифровать сообщение, выступая в роли асимметричного шифра. Учебный пример зашифрования состоит в возведении сообщения, представленного в виде числа, в шифрующую степень и вычислении остатка по модулю N (заданному в составе ключа). C = m e mod N, где C — шифротекст, а m — открытый текст. Соответственно, зная расшифровывающую экспоненту, можно расшифровать C: m = C d mod N. Это соотношение можно проиллюстрировать следующим нестрогим рассуждением, используя тот факт, что e = d -1 (mod (p-1)(q-1)), поэтому: C d = (m e ) d = m e*d = m e*e -1 = m 1 = m. В рамках данной статьи не рассматривается несложный математический аппарат RSA и не приводится доказательство корректности операций (доказательство, основанное на малой теореме Ферма, нетрудно найти в тематической литературе).

Из-за возможности проведения эффективной атаки, RSA нельзя использовать подобным способом, непосредственно зашифровывая сообщение. Допустимым вариантом является, например, зашифрование RSA случайного секрета, дополненного специальным образом до разрядности модуля, с последующим вычислением ключа симметричного шифра при помощи хеш-функции от переданного секрета — именно эта схема входит в спецификации TLS (однако использование RSA для обмена сессионными секретами в настоящее время считается устаревшим методом).

Генерация ключей RSA начинается с генерации пары простых чисел, которые составят модуль. Знание p и q позволяет легко определить обратную к шифрующей экспоненту. Однако задача разложения числа на простые множители является вычислительно сложной. Фактически, для достаточно больших чисел (2048 бит и более), сейчас не известно алгоритмов, позволяющих находить разложение произвольных чисел за «разумное время» с использованием любых технологически мыслимых вычислительных мощностей. Существует, — пока сугубо теоретическая, но отлично обоснованная, — возможность быстрой факторизации при помощи алгоритма Шора на квантовом компьютере достаточной разрядности (под вопросом находится сама возможность создания подходящего компьютера). «Квантовая атака» касается не только RSA, но также и описанных выше вариантов DH, и криптосистемы электронной подписи ECDSA. Так как применимость квантового компьютера зависит от его доступной разрядности — от количества рабочих кубитов, — то, например, ECDSA будет взломана раньше RSA, так как ECDSA использует ключи существенно меньшей разрядности (типичные значения: 256 бит против 4096 у RSA).

При использовании для создания и проверки электронной подписи RSA работает следующим образом. Сторона, генерирующая подпись, вычисляет значение хеш-функции от подписываемого сообщения M, а именно — H = Hash(M), приводит это значение к разрядности используемого модуля N и вычисляет значение подписи при помощи секретной (расшифровывающей) экспоненты: S = H d mod N. То есть, с арифметической точки зрения, происходит следующее: значение H, рассматриваемое как двоичная запись натурального числа, возводится в степень с показателем d, а для полученного значения вычисляется остаток от деления на N. На практике используются некоторые существенные оптимизации, а процесс вычисления называется «возведением в степень по модулю числа N».

Для проверки подписи требуется знать открытую часть ключа: модуль и шифрующую экспоненту e. Значение подписи возводится в степень e, а получившееся значение сравнивается с вычисленным значением H хеш-функции сообщения: S e (mod N) == H. Если значения совпали, то подпись верна. Для вычисления корректной подписи (подделки), соответствующей заданному сообщению, третьей стороне необходимо знать секретную экспоненту d. Защиту обеспечивает следующий факт: для быстрого определения d по известным параметрам e и N потребуется найти разложение N на простые множители, а это вычислительно трудно.

Механизм электронной подписи RSA (как и ECDSA) используется для удостоверения параметров протокола Диффи-Хеллмана, переданных сервером в сообщении ServerKeyExchange. Подпись S, передаваемая в составе сообщения TLS, является целым числом, имеющим разрядность, соответствующую разрядности модуля ключа. Модуль ключа N содержится в сертификате сервера. Так, если модуль имеет разрядность 2048 бит, то для записи подписи потребуется 256 байтов (256*8 = 2048). Подпись, как отмечено выше, вычисляется от значения хеш-функции для объединения параметров DH (в них входит и серверная часть), кроме того, в TLS 1.2 к параметрам добавляются значения ServerRandom и ClientRandom. В процессе вычисления значения подписи параметры преобразуются к формату, требуемому алгоритмом применения RSA.

При прямой передаче сеансового секрета на сервер, RSA применяется самым хрестоматийным образом: открытый ключ извлекается из сертификата сервера, сгенерированный секрет преобразуется к установленному формату, а результат возводится в степень, заданную шифрующей экспонентой. Получившееся зашифрованное сообщение передаётся в ClientKeyExchange (как описано выше). Сервер, которому известно значение секретной экспоненты, расшифровывает полученное сообщение. Предполагается, что если в ход установления соединения вмешалась третья сторона, подменившая сервер, то этой стороне не удастся корректно расшифровать переданный клиентом секрет, соответственно, стороны не смогут прийти к общему набору сеансовых ключей. Интересно, что для обхода данного ограничения перехватывающей стороне не требуется строго сам секретный ключ, значение которого нигде не участвует, а достаточно, чтобы была возможность расшифровать данные, например, отправив запрос серверу. Такая схема иногда используется при делегировании полномочий по инспекции TLS-трафика третьей стороне, без передачи самого секретного ключа (однако в отношении RSA схема вовсе не является полностью безопасной: можно заметить, что операции с секретной экспонентой эквивалентны генерированию RSA-подписи). Данный метод получения сеансового секрета использовать не рекомендуется.

Другое историческое применение RSA, как асимметричного шифра в TLS, возможно при выборе сервером варианта протокола установления соединения, использующего временные ключи RSA. В таком случае сервер передаёт модуль и значение открытой экспоненты в составе сообщения ServerKeyExchange. Клиент использует полученный открытый ключ RSA для того, чтобы зашифровать случайные байты ClientKeyExchange, которые послужат для генерации симметричных ключей. Эта экзотическая схема была актуальна для «экспортных» вариантов протокола, когда от реализации требовалось, чтобы для защиты сессии не применялись ключи RSA длиннее 512 бит: сервер использовал «длинный» ключ из сертификата для подписывания «короткого» временного ключа из ServerKeyExchange. Сейчас RSA в TLS не следует использовать в качестве асимметричного шифра, это небезопасно (тем более, с коротким ключом).

Важно учитывать, что математическая эквивалентность операций получения электронной подписи и расшифрования в RSA является особенностью данной криптосистемы, не более того. Операции подписывания и зашифрования/расшифрования — это разные операции, их совпадение в RSA не означает, что другие криптосистемы электронной подписи могут прямо служить шифрами (хотя построить шифр на базе такой криптосистемы обычно можно).

Для RSA предложено большое количество теоретико-числовых атак. Часть этих атак можно эффективно применить к дефектам и ошибкам в той или иной реализации RSA, что делает атаки не только практическими, но и весьма быстрыми. Криптосистема RSA считается устаревшей в целом, что, впрочем, не мешает ей оставаться очень популярной.

Рассмотрим фрагмент трафика установления TLS-соединения, в котором узлы договорились использовать шифронабор с передачей сеансового секрета с помощью шифрования RSA (а именно: TLS_RSA_WITH_AES_128_CBC_SHA). Сертификат, представленный сервером, содержит открытый ключ длиной 2048 бит. Этот ключ используется клиентом для зашифрования. О том, что клиент прислал именно зашифрованный RSA секрет — сервер знает потому, что RSA указана в шифронаборе, соответственно, рассматриваемое сообщение ClientKeyExchange не содержит никакого указания на то, что используется именно RSA, с тем или иным ключом.

Смещение Байты Комментарий (десятичное) (шестнадцатеричное представление) 0000 16 03 03 ; Handshake, TLS 1.2. 0003 01 06 ; Длина: 0x0106 = 262 байта. 0005 10 ; Сообщение ClientKeyExchange (0x10). 0006 00 01 02 ; Длина: 0x000102 = 258 байт. 0009 01 00 ; Длина блока PreMasterSecret: 0x0100 = 256 байт. Длина соответствует разрядности ключа из сертификата - 2048 бит. 0011 54 . ; Далее идёт зашифрованный блок из 256 байтов. Из них 48 байтов (46+2) - это PreMasterSecret, остальные байты содержат дополнение, необходимое для корректного использования RSA.

Криптосистема ECDSA

ECDSA является эллиптическим вариантом криптосистемы электронной подписи DSA. Последняя (DSA) — сейчас практически не используется. Интересно, что она, в свою очередь, является вариантом схемы подписи Эль-Гамаля, которая представляет собой алгоритм, построенный на базе задачи дискретного логарифмирования, и, таким образом, имеющий прямое родство с классическим протоколом Диффи-Хеллмана.

Идею схемы ECDSA можно изложить следующим образом: предложим такую пару алгоритмов для генерации значения подписи и проверки этого значения, которые будут «сходиться» к одному значению только в том случае, если стороны использовали ключи из связанной однонаправленной функцией пары (это, впрочем, очевидная схема для ЭЦП). В качестве однонаправленной функции используется умножение точки эллиптической кривой на скаляр. При этом подписи «рандомизируются», для чего служит дополнительный параметр — ещё одна точка кривой. При успешной проверке, результат, полученный проверяющей стороной, совпадёт с этой дополнительной точкой — откуда и возникает, достаточно условное, представление о том, что схемы сходятся «в одной точке». ECDSA существенно отличается от RSA, как по составу и свойствам параметров, ключей, так и по алгоритмам генерации подписи и её проверки. ECDSA, вообще говоря, несколько сложнее. Ключевым является тот факт, что обе основные части криптосистемы ECDSA — алгоритм вычисления подписи и алгоритм проверки, — представляют собой две части единого базового соотношения.

Итак, прежде чем использовать ECDSA, стороны должны согласовать общие параметры: выбрать кривую E (она традиционно задаётся парой чисел); выбрать конечное поле, над которым будут производиться операции на кривой (кривая, как и в ECDH, используется в целочисленной форме; «конечное поле» — упрощённо можно считать, что это тоже выбор одного простого числа или степени простого числа); выбрать соответствующую общую точку на кривой — генератор G. Точка — это пара значений (x,y), которые далее называются координатами. (x,y) — элементы соответствующего поля (упрощённо — натуральные числа, меньше некоторого заданного; остатки деления). Как и в случае с «эллиптическим» вариантом DH, на кривой задана операция сложения точек — это та же самая операция, которая используется и в ECDH (см. выше). На этой операции строится алгоритм удвоения точки и умножения на скаляр. Именно умножение на скаляр является основой криптосистемы (опять же, аналогично ECDH). Так как используется аддитивная запись, то речь идёт именно об умножении, однако в мультипликативном случае ему соответствовало бы возведение в степень, отсюда и возникает «логарифмирование». Если у нас есть точка N на кривой, то умножение на скаляр dN — тоже даёт точку (B) на кривой. Задача вычисления d по известным N, B и есть задача дискретного логарифмирования в группе точек эллиптической кривой, уже знакомая из описания протокола Диффи-Хеллмана.

Открытый ключ в ECDSA — это точка Q на кривой, полученная умножением выбранного генератора G на целое положительное число d: Q = dG. Соответственно, d — является секретным ключом. Схема в этой части напоминает RSA, только в данном случае в состав открытого ключа не входит некий модуль (но модуль используется при задании параметров криптосистемы). Генератор G является публичным значением, но, как было только что отмечено, для того, чтобы определить d, потребуется отыскать соответствующий логарифм, что нереализуемо на практике (при условии правильно выбранных параметров криптосистемы). Открытый ключ, таким образом, представляет собой пару чисел (xq,yq) — так как точке соответствует две координаты. Важно понимать, что эти координаты — это просто пара элементов поля, удовлетворяющих уравнению кривой. То есть, можно рассматривать кривую с операцией умножения точки на скаляр, как некоторую структуру, заданную поверх пар элементов выбранного поля (упрощённо — пар больших натуральных чисел). При этом умножение точки кривой на скаляр — это операция в группе точек кривой, а не в поле. А именно: умножению точки на скаляр d (натуральное число) соответствует (d-1) операций сложения точек, каждая из которых ставит в соответствие двум парам элементов поля, возможно, совпадающим, — третью пару, так как одна точка характеризуется именно парой элементов поля. На практике, так как используется конечное поле, его элементы всегда можно пронумеровать натуральными числами, что позволяет эффективно проводить компьютерные вычисления. Но следует учитывать, что операции в поле и на кривой не будут совпадать с привычными операциями над натуральными числами (которые поля не образуют). Дополнительные сведения о соответствующем математическом аппарате приведены в Приложении А.

Для вычисления подписи в ECDSA используется хеш-функция, позволяющая получить «сжатое» представление сообщения M: H = Hash(M). Значение H приводится к разрядности выбранных параметров. В описании ниже — n обозначает порядок генератора G в группе кривой, то есть nG = 0 (0 — нейтральный элемент группы точек кривой). Схема существенным образом базируется на «рандомизации» — каждая подпись использует случайный параметр k, который не должен повторяться. (Существует так назваемый «детерминированный вариант» ECDSA, но мы его здесь не рассматриваем, тем более, что все его особенности являются глубоко техническими, а принципы верхнего уровня полностью совпадают с «обычной» ECDSA.) Уникальность k является фундаментальным требованием для обеспечения стойкости, поскольку повторное использование позволяет вычислить секретный ключ. Это, пожалуй, самая часто упоминаемая в литературе особенность ECDSA, но, тем не менее, ошибки тут всё равно встречаются. Именно на некорректном повторном использовании k основывался нашумевший взлом системы защиты ПО Sony Playstation в 2010 году.

  • 1) выбирается уникальное (псевдо)случайное число k (соответствующее интервалу [1,n-1]);
  • 2) вычисляется точка kG (где G — это генератор, заданный в параметрах). Данная точка на кривой является точкой, задающей конкретное значение подписи, связывающей алгоритм проверки подписи с алгоритмом генерации. Точке kG соответствуют координаты (x,y);
  • 3) для x вычисляется значение r = x mod n (то есть, остаток от деления x на порядок генератора G; r — это первая часть значения подписи; если r = 0, что крайне маловероятно, то алгоритм возвращается к шагу 1);
  • 4) вычисляется значение s = k -1 (H + rd) mod n. k -1 — это обратный к k элемент (относительно умножения) по модулю n, его несложно вычислить;
  • 5) пара (r,s) — и есть значение электронной подписи.
  • 1) вычисляется значение v = s -1 mod n;
  • 2) вычисляется значение u1 = Hv mod n;
  • 3) вычисляется значение u2 = rv mod n;
  • 4) определяется точка B на кривой = u1G + u2Q. Здесь G — генератор, заданный в параметрах, а Q — открытый ключ. Умножение — обозначает умножение точки кривой на скаляр; сложение — сложение точек на кривой;
  • 5) если для координаты x точки B выполняется r = x mod n, то подпись считается действительной.
  • k = s -1 (H+rd) = s -1 H+s -1 rd = (Hv) + (rv)d = u1 + u2d;
  • мы нашли, что u1 + u2d = k; здесь k — случайный параметр подписи, а d — секретный ключ, соответствующий Q;
  • преобразования следуют из соотношений, заданных в алгоритме проверки и связывают открытый ключ, случайный параметр k и значение подписи, относительно значения H (хеш сообщения);
  • Q = dG, что позволяет выполнить следующую замену: u1G + u2Q = u1G + u2dG = (u1 + u2d)G = kG (соответствует исходной точке, определённой на шаге 2 алгоритма вычисления подписи);
  • таким образом, если подпись действительно получена от ключа Q, то r = x mod n (ведь x — это координата, соответствующая точке kG).

ECDSA используется как в TLS-сертификатах, так и для удостоверения серверных параметров DH. При этом ECDSA нельзя использовать для зашифрования, а только для получения и проверки электронной подписи.

Рассмотрим фрагмент трафика TLS-сессии — это сообщение ServerKeyExchange, в котором передаются параметры протокола Диффи-Хеллмана на эллиптических кривых (ECDH), подписанные ECDSA.

Смещение Байты Комментарий (десятичное) (шестнадцатеричное представление) 0000 16 03 03 ; Handshake, TLS 1.2. 0003 00 95 ; Длина: 0x0095 = 149 байтов. 0005 0c ; ServerKeyExchange. 0006 00 00 91 ; Длина: 0x000091 = 145 байт. 0009 03 00 17 ; Серверные параметры ECDH: 0x03 - префикс именованной кривой; 0x0017 - обозначение кривой secp256r1. 0012 41 ; Длина блока серверной части DH: 0x41 = 65 байт. 0013 04 f3 52. ; Значение серверной части DH - это точка на кривой secp256r1. [. ] 0078 06 03 ; Тип подписи и хеш-функции. 0x06 - хеш-функция SHA-512; 0x03 - тип подписи ECDSA. 0080 00 48 ; Длина блока значения подписи: 0x0048 - 72 байта; 0082 30 ; Далее идёт значение подписи. Значение представляет собой ; пару целых чисел (r,s). Числа имеют разрядность, соответствующую ; разрядности группы кривой (в данном случае: 256 бит, то есть, 32 ; байта на одно число). Пара кодируется в соответствии с ASN.1, в ; двоичном представлении. Таким образом, для записи двух чисел ; потребуется 32 * 2 = 64 байта. Остальные байты содержат служебные ; значения кодирования ASN.1. Так, 0x30 - обозначает, что будет ; передана последовательность (SEQUENCE). Следующий байт - длина ; последовательности в октетах. 0083 46 ; Длина последовательности ASN.1: 0x46 = 70 байт (октетов). 0084 02 ; Префикс, обозначающий в ASN.1 тип INTEGER (целое). 0085 21 ; Длина записи значения INTEGER: 0x21 = 33 байта (октета) (32+1). 0086 00 98 8b. ; Далее идёт значение первого элемента подписи, 33 байта. ; Так как само число 32-байтовое, первый байт содержит ; значение 00. [. ] 0119 02 21 ; Аналогичные предыдущему числу поля ASN.1: INTEGER (0x02), ; 33 (0x21) октета. 0121 00 99 26. ; Значение второго элемента подписи (33 байта, первый - 00).

Параметры криптосистем

  • для «классического» варианта протокола Диффи-Хеллмана это модуль, задающий группу, а также генератор в ней;
  • для ECDH (на эллиптической кривой) — параметры кривой, включающие поле, над которым кривая используется, и, опять же, генератор;
  • для RSA — шифрующая экспонента и модуль;
  • для ECDSA — параметры кривой и генератор.

Наибольшее число параметров требуется для эллиптических криптосистем. В TLS для них принято использовать типовые кривые, обозначенные зафиксированными именами, но при установлении соединения в версиях ниже 1.3 можно указать и любую другую кривую. В TLS 1.3 — параметры зафиксированы строго. Очевидно, и сервер, и клиент должны соответствующую кривую поддерживать. Каждому типовому набору соответствует сама кривая и поле, над которым проводятся операции. Реестр имён и индексов ведёт IANA, названия определены в RFC 4492, RFC 7027 и др. Конкретные параметры — определены в сопутствующих документах NIST, ANSI и др. В 2016 году соответствующий реестр IANA переименован в «Реестр поддерживаемых групп» («Supported Groups Registry»), что лучше соответствует математической действительности, потому что используемые в TLS криптосистемы работают в группах, просто, в ряде случаев, это группы точек эллиптической кривой.

С именованием кривых существует некоторая исторически сложившаяся путаница. Например, кривая, распространённая в сертификатах, используемых для HTTPS, называется prime256v1, она же — secp256r1, она же — NIST P-256; а параметры этой кривой определены, в частности, в рекомендации NIST 186-4.

Типичные параметры ECDSA, на примере NIST P-256 (источник: SafeCurves, там же представлены сводные данные по всем другим распространённым кривым):

-- Уравнение кривой: y2 = x3-3x+41058363725152142129326129780047268409114441015993725554835256314039467401291 Кривые определяются параметрами a,b уравнения: y2 = x3 + ax + b Соответственно: a = -3 b = 41058363725152142129326129780047268409114441015993725554835256314039467401291 -- Поле; значение задающего модуля P (простое число): P = 115792089210356248762697446949407573530086143415290314195533631308867097853951 = 0xffffffff00000001000000000000000000000000ffffffffffffffffffffffff = 2256 - 2224 + 2192 + 296 - 1. -- Генератор G. Точка на кривой, заданная парой координат (x,y): (48439561293906451759052585252797914202762949526041747995844080717082404635286, 36134250956749795798585127919587881956611106672985015071877198253568414405109) = (0x6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296, 0x4fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5) -- Порядок генератора G; n (простое число): 115792089210356248762697446949407573529996955224135760342422259061068512044369 = 0xffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc632551 = 2256 - 2224 + 2192 - 89188191075325690597107910205041859247

Сертификаты

TLS-сертификаты (SSL-сертификаты — устаревшее название, являющееся синонимом) играют важную роль в современной инфраструктуре TLS. У TLS-сертификата одно предназначение: привязать открытый ключ к некоторому сетевому имени. Например, сопоставить ключ 0xA3FEF7. DA3107 имени example.com. TLS-сертификаты не содержат никакой секретной информации. Они не являются непосредственными носителями ключей шифрования передаваемых данных в TLS (за исключением открытого серверного ключа RSA, который может быть использован для зашифрования сеансового секрета в устаревших режимах работы TLS).

Открытый ключ, который содержится в сертификате, принадлежит искомому серверу, с которым клиент планирует установить соединение. Однако открытый ключ может быть подменён третьей стороной на другой, имитирующий легитимный ключ сервера. Для того, чтобы можно было обнаружить подобную подмену, служит инфраструктура удостоверяющих центров, которая даёт клиенту механизм проверки принадлежности ключа. То есть клиент соглашается верить некоторой третьей стороне (не злоумышленнику, а удостоверяющему центру — УЦ), что эта третья сторона проверила соответствие ключа и сетевого имени (в вебе это обычно домен). Результат такой проверки подтверждается подписью УЦ, которую он ставит на сертификате сервера. Для подписи сейчас используются криптосистемы RSA и ECDSA.

Предполагается, что клиент TLS имеет в своём распоряжении некоторый набор сертификатов удостоверяющих центров (часть из этих сертификатов является корневыми) и может проверить подписи на предоставляемых сервером сертификатах, выстроив цепочку доверия, ведущую от серверного ключа к одному из доверенных корней. На практике, в браузеры встроены многие десятки корней, соответствующих различным УЦ. Для выстраивания цепочки доверия определяющее значение имеет именно корневой ключ, а не сам сертификат, который его содержит. Тем не менее, в сертификате содержатся имена, которые позволяют отличить один ключ от другого и сопоставить отдельные сертификаты друг другу.

В SSL/TLS используются сертификаты формата X.509, это очень старый формат, изначально разрабатывавшийся для телеграфа, но позже адаптированный для использования в Интернете, в частности, в вебе.

Сертификат представляет собой электронный документ, имеющий определённую спецификацией структуру. Так, каждый сертификат содержит поля Issuer и Subject. Поле Issuer определяет имя стороны, выпустившей данный сертификат (поставившей на нём подпись), а поле Subject — имя стороны, для которой сертификат выпущен. В случае веба, в Issuer обычно указано имя из сертификата УЦ (не обязательно корневого), а в Subject, для серверного сертификата, — доменное имя, адресующее сайт. В 2017 году в браузере Google Chrome появилось новшество: для валидации сертификата по имени сервера, это имя должно быть указано не в Subject, а в расширении сертификата под названием SAN (Subject Alternative Name).

Клиент получает сертификаты (в большинстве случаев — это цепочка, но может быть и единственный серверный сертификат) в сообщении Certificate (см. выше), выстраивает их в иерархию, где каждый сертификат удостоверяет следующий, проверяет подписи и соответствие имени из серверного сертификата имени сервера, с которым планирует установить соединение. Проверка имени является важнейшим аспектом, так как злоумышленник может выпустить доверенный сертификат для своего имени сервера, но предъявлять его под именем другого сервера (перехватив сеанс тем или иным способом). В таком случае полностью валидный сертификат злоумышленника будет отличаться от легитимного только указанным именем и ключом. Например, сертификат выпущен для example.com, а предъявляется для test.ru. (Такое несоответствие также является одной из самых распространённых ошибок настройки TLS-серверов.)

Сертификат выпускается на определённый срок, который указан в самом сертификате. Сертификат может быть отозван, по какой-то причине, раньше окончания срока действия. Браузеры и другие TLS-клиенты должны проверять статус отзыва сертификатов, для этого существует ряд механизмов, однако в повседневной реальности проверка отзыва сертификатов, фактически, не работает — этот момент нужно учитывать при анализе рисков.

Посмотрим на пример TLS-сертификата — это расшифровка полей сертификата, выпущенного для dxdt.ru УЦ WoSign, полученная утилитой openssl x509:

Version: 3 (0x2) ; Версия спецификации, обычно - 3 Serial Number: 58:04:6c:41:4b:a3:02:a0:a7:c1:13:a3:07:53:97:90 ; Серийный номер сертификата. На генерацию серийных номеров наложены определённые требования. Так, номера не должны быть предсказуемыми, не должно быть двух различных сертификатов одного УЦ с одинаковым серийным номером. Signature Algorithm: sha256WithRSAEncryption ; Алгоритм подписи: это RSA-сертификат, с RSA-подписью, использующей хеш-функцию SHA-256. Issuer: C=CN, O=WoSign CA Limited, CN=WoSign CA Free SSL Certificate G2 ; Имя стороны, выпустившей сертификат: WoSign. Это простое текстовое поле, определённого формата. В сертификате имеет значение каждый байт, это касается и имени в Issuer. Validity Not Before: May 5 23:50:37 2015 GMT Not After : May 6 00:50:37 2018 GMT ; Срок действия сертификата. Не ранее - не позднее. Subject: CN=dxdt.ru ; Имя, для которого выпущен сертификат - в нашем случае это dxdt.ru. Обратите внимание, что если не указано дополнительных имён DNS (см. ниже), сертификат будет валиден только для для dxdt.ru, для www.dxdt.ru такой сертификат не подойдёт. Возможен выпуск сертификатов для имён с маской подстановки: *.dxdt.ru. В этом случае сертификат будет валиден для любого имени третьего уровня в dxdt.ru, например для tls.dxdt.ru или static.dxdt.ru, однако для dxdt.ru - сертификат окажется невалидным. Subject Public Key Info: ; Данные открытого ключа сервера. Public Key Algorithm: rsaEncryption ; Алгоритм - используемая криптосистема (RSA). Public-Key: (2048 bit) ; Сам ключ (разрядность 2048 бит). Открытый ключ RSA (как описано выше) состоит из модуля и шифрующей экспоненты, обычно она выбирается из типовых значений, удобных для оптимизации вычислительных операций. Modulus: 00:c4:c5:f6:49:02:50:3b:d2:9d:b6:d6:cd:19:80: 0f:66:a0:c9:eb:6b:b5:05:c5:52:e3:d9:09:25:a0: 2e:86:d8:e5:20:0c:39:66:bb:03:57:3e:23:a5:f7: 98:2d:99:16:f6:70:d4:87:c6:76:86:79:78:6a:4f: bd:61:6a:89:23:7d:8c:dd:fc:8b:8f:d6:91:a5:33: ed:df:35:b0:ee:cb:e7:43:1e:5a:8c:7e:e9:49:c3: 82:2a:95:9f:f1:a6:86:61:22:97:81:df:2b:55:b8: f4:ad:0e:c1:f6:d2:c6:66:31:d3:57:a0:51:1e:5f: 7e:ce:d3:ba:27:21:cd:16:66:e5:22:e5:64:45:46: 64:8f:6a:f1:6c:2d:f2:8e:28:c1:72:27:3b:bf:8a: 10:56:c0:16:94:ec:60:c1:70:c0:c2:3d:28:8b:5c: 4c:44:e2:ac:67:1a:e7:93:ec:ec:1f:9b:a1:30:f6: 71:95:77:8d:8d:d4:d4:43:4e:1f:5e:5b:13:a9:48: 1d:c2:a3:87:26:e6:65:8a:ff:75:fb:84:c9:67:e3: 88:51:28:b2:2c:45:3a:7f:37:68:dd:da:14:73:c7: 71:b7:1c:ea:ea:d3:08:b4:a8:6b:8d:df:f6:be:71: 07:f0:fe:5c:b4:4e:15:de:2e:d8:96:8b:15:96:83: b4:c3 ; Модуль (2048 бит). Exponent: 65537 (0x10001) ; Экспонента. ; Далее идут расширения формата, играющие важную роль в современной инфраструктуре TLS-сертификатов. Ряд из этих расширений имеет прямое отношение к работе TLS. X509v3 extensions: X509v3 Key Usage: Digital Signature, Key Encipherment ; Указание на допустимое использование ключа из сертификата: в данном случае ключ может быть использован для создания подписи и для зашифрования других ключей. Первый вариант необходим при использовании сеансового ключа по алгоритму Диффи-Хеллмана; второй - для передачи клиентом зашифрованного секрета. Значения из этого поля проверяются клиентом, например, браузером. X509v3 Extended Key Usage: TLS Web Client Authentication, TLS Web Server Authentication ; Дополнительные параметры использования ключа: допускается применение для аутентификации веб-клиента и веб-сервера (традиционное использование). X509v3 Basic Constraints: CA:FALSE ; Ограничения на использование ключа и сертификата: данный сертификат не является сертификатом УЦ, то есть от него не должны выпускаться другие сертификаты. Технически, никаких проблем с выпуском ещё одного сертификата, подписанного ключом данного, нет. Однако при выстраивании цепочки доверия, клиент (например, браузер), должен сверять статусы сертификатов и доверять только подписям, полученным от сертификатов, для которых в этом поле указано CA:TRUE. Интересно, что браузер Microsoft IE длительное время, до 2003 года, некорректно проверял статус сертификата (из-за ошибки в коде), что позволяло выпускать валидные, с точки зрения IE, сертификаты для любого имени, приобретя обычный серверный сертификат у того или иного УЦ. X509v3 Subject Key Identifier: 37:93:60:97:E7:8A:3C:FF:C6:68:6A:DD:97:92:A5:32:59:87:8A:E4 X509v3 Authority Key Identifier: keyid:D2:A7:16:20:7C:AF:D9:95:9E:EB:43:0A:19:F2:E0:B9:74:0E:A8:C7 ; Специальные идентификаторы ключей, позволяющие клиенту быстрее найти соответствующие ключи в сертификатах в своих хранилищах. Это особенно актуально для поиска подходящего ключа УЦ, так как ускоряет построение цепочки валидации. Authority Information Access: OCSP - URI:http://ocsp6.wosign.com/ca6/server1/free CA Issuers - URI:http://aia6.wosign.com/ca6.server1.free.cer ; Адреса: ответчика OCSP (Online Certificate Status Protocol) - это протокол онлайн-проверки статуса отзыва сертификата; и сертификата УЦ, от которого выпущен данный сертификат. X509v3 CRL Distribution Points: Full Name: URI:http://crls6.wosign.com/ca6-server1-free.crl ; Существует метод отзыва сертификатов при помощи выпуска списков отозванных сертификатов (CRL - Certificate Revocation List). Данное поле содержит адрес, по которому список доступен. X509v3 Subject Alternative Name: DNS:dxdt.ru, DNS:www.dxdt.ru, DNS:tls.dxdt.ru ; Дополнительные имена. Это расширение очень полезно, так как позволяет указать дополнительные имена, для которых валиден данный сертификат. Например, здесь указаны www.dxdt.ru и tls.dxdt.ru. X509v3 Certificate Policies: Policy: 2.23.140.1.2.1 Policy: 1.3.6.1.4.1.36305.6.1.2.2.1 CPS: http://www.wosign.com/policy/ ; Перечень политик, которым соответствует данный сертификат. Политики устанавливаются УЦ (в соответствии с некоторыми нормами, если УЦ желает, чтобы его корни были включены в распространённые браузеры), но являются чисто административным инструментом, напрямую не относящимся к криптографии, хотя и влияющим на используемые механизмы. Например, именно политика определяет, будет ли сертификат расцениваться как сертификат "Расширенной проверки" (EV). Signature Algorithm: sha256WithRSAEncryption 09:20:65:da:92:9f:93:d2:96:55:80:51:8e:06:3a:37:c1:26: 33:af:da:2a:63:0e:da:c2:b2:c9:31:80:b3:de:9a:b2:48:ce: 3b:11:ee:a7:81:fc:9e:48:5d:a0:59:6f:b6:d0:e7:da:c9:86: 47:79:ef:ea:71:cd:72:2f:b1:7d:ac:84:88:84:c5:a8:19:47: 4d:6b:1c:e0:8f:81:b0:c9:13:95:c9:f7:27:7a:93:2b:2c:08: ac:c8:69:2d:0d:4f:c6:4d:b7:18:96:4f:50:c0:0f:23:20:cf: 22:28:5d:fd:e5:89:dd:c9:1d:9c:c6:b3:54:4b:65:e5:8d:2e: 26:07:85:fb:d4:d8:23:ed:30:dc:60:33:da:9e:85:79:37:1d: ec:04:87:ad:c2:00:7b:87:06:7e:ee:26:27:25:ef:4a:5c:8f: 64:0f:77:28:3f:69:61:37:36:f8:40:78:8d:7d:00:f3:2f:e7: fb:5b:c6:52:c4:5e:e5:19:54:06:ad:3f:7d:48:19:59:82:ef: 46:96:3b:fc:71:3f:4f:99:94:d5:1d:c2:80:44:e6:af:3c:cf: 01:c2:4c:e7:e8:53:8b:56:ad:06:c7:c9:23:90:7e:93:1d:f5: f6:2e:29:21:ae:13:23:da:7a:f9:04:ea:62:8c:e3:24:f1:05: db:0d:e5:1f ; Значение подписи сертификата. Подпись вычисляется от значения хеш-функции, аргументом которой является весь сертификат (за исключением, соответственно, подписи). Генерируется подпись при помощи секретного ключа УЦ, соответствующего сертификату с именем, указанным в Issuer.

Итак, TLS-сертификаты являются важным элементом TLS, позволяющим проводить аутентификацию. Ключи из сертификатов используются при генерации общего секрета. В теории, возможно установление анонимного TLS-соединения без использования сертификатов (это не запрещено спецификацией, а серверное сообщение Certificate не является строго обязательным), однако массово применяемые на практике методы генерации сеансового ключа основываются на использовании серверного сертификата (а точнее — на использовании открытого ключа из сертификата).

Основные современные претензии к TLS-сертификатам касаются сложившейся административной структуры УЦ. Так, пока что никакая распространённая технология не мешает УЦ выпустить «подменный» сертификат, позволяющий прозрачно перехватывать TLS-соединения, используя атаку типа «человек посередине» (см. ниже в разделе про перехват HTTPS). Но такие технологии разрабатываются и успешно внедряются, к ним относится инициатива Certificate Transparency (поддерживаемая Google), Certificate Pinning или Public Key Pinning, когда в браузерах сохраняются (и обновляются) заведомо корректные для данного узла сертификаты или открытые ключи, а также технология DANE, использующая DNS в качестве дополнительной системы контроля.

Шифры в TLS

Как рассказано выше, TLS использует для защиты информации шифронаборы. Шифронабор (Cipher Suite) позволяет обеспечить не только сокрытие информации, но и её целостность. В состав шифронабора входит симметричный шифр. С его помощью осуществляется зашифрование потока данных, передаваемых через TLS-сокет. Возможно использование TLS без шифрования, однако это не является распространённым случаем.

В терминологии TLS существуют зашифровывающие и расшифровывающие функции. Эти функции работают с криптографическим контекстом соединения, о котором договорились узлы. После того, как узлы обменялись сообщениями ChangeCipherSpec (см. выше), все TLS-сообщения зашифрованы, а в TLS 1.3 шифрование включается даже раньше. Зашифровывающая функция преобразует открытый текст, подготовленный для отправки в составе TLS-записи (строго говоря, после сжатия, но, как рассказано выше, в современной реальности TLS сжатие не используется), в секретный текст (зашифрованный). Расшифровывающая функция выполняет обратное преобразование. Для того, чтобы зашифровывающие и расшифровывающие функции успешно работали на обоих узлах, требуется выработка общего криптографического контекста — это происходит в рамках обмена сообщениями Handshake. В TLS могут использоваться и потоковые, и блочные шифры, последние — в различных режимах. Обычно, зашифровывающие и расшифровывающие функции являются одним симметричным шифром и различаются только составом ключей. TLS 1.3 существенно ужесточает принципы включения шифронаборов в реализации, фактически, в действующей версии 1.3 допущены только два шифра: AES и ChaCha20.

Шифр — это некоторый набор обратимых преобразований данных, каждое из которых определяется параметром — ключом шифрования. Порядок применения этих преобразований к входным сообщениям принято называть режимом шифрования. Простейшая криптосистема может включать лишь один шифр, то есть, грубо говоря, состоять из одного алгоритма зашифрования и (обратного к нему) алгоритма расшифрования. В симметричных системах, которые используются в TLS, знание шифрующего ключа позволяет легко получить расшифровывающий ключ, то есть расшифровать секретное сообщение. В используемых сейчас массовых симметричных криптосистемах шифрующий и расшифровывающий ключи просто совпадают, поэтому обычно говорят об одном и том же ключе. Другими словами, симметричные системы подразумевают, что обе стороны, обменивающиеся информацией по закрытому каналу, знают некий общий секрет ― например, секретный симметричный криптографический ключ, который позволяет как зашифровывать, так и расшифровывать сообщения. Обратите ещё раз внимание на то, что в TLS используется набор из двух ключей (ключ «записи» и ключ «чтения»), но эти наборы симметричны, на стороне клиента или сервера — ключи просто меняются местами: серверная «запись» становится «чтением» клиента.

Симметричные криптосистемы — первые из придуманных человечеством. Историческими примерами симметричных криптосистем являются так называемые «наивные» шифры — например, шифры простой замены букв текста на естественном языке, где в качестве ключа может выступать та или иная перестановка алфавита. Современные шифры, вроде AES или 3DES, тоже являются симметричными. К симметричным относится и единственная криптосистема, обладающая абсолютной стойкостью — шифр Вернама, с равновероятным одноразовым ключом, равным по длине шифруемому сообщению (одноразовый шифр-блокнот). Шифр Вернама не очень удобен, поэтому нечасто используется на практике. Однако основная идея этого шифра послужила прообразом самых защищённых режимов шифрования в TLS.

В основе логики построения современных шифров лежит задача сокрытия статистических свойств исходного открытого текста. То есть, шифр стремятся спроектировать таким образом, чтобы его вывод был вычислительно неотличим от результата (псевдо)случайной функции (точнее — перестановки, но это комбинаторные детали). Дело в том, что попытка скрывать лишь сами символы открытого текста не даёт никакой секретности. Игрушечным, но весьма показательным, примером является шифр простой замены, где буквы открытого текста заменяются на какие-то другие символы (например, на специально выдуманные «иероглифы»). Каждая буква неузнаваема, но прочитать такой шифротекст легко, если известно, на каком языке был записан открытый текст, так как статистические свойства открытого текста прямо наследуются: частотность «иероглифов» соответствует известной частотности букв в тексте на исходном языке. Эта классическая «дешифровка» многократно описана в художественной литературе. Соответственно, современные криптосистемы прежде всего направлены на сокрытие статистических свойств открытого текста, на «размытие» статистики «до уровня случайности». (Важно отметить, что при правильном выборе процедуры генерации ключей, шифр простой замены может быть сделан чрезвычайно стойким, вплоть до невозможности вскрытия персонажами художественного произведения.)

Криптосистемы строятся на базе некоторых «примитивов» — своего рода строительных блоков, которые выполняют базовые операции над данными. К базовым операциям относятся подстановки, перемешивание, сложение и умножение (выполняемые по модулю некоторого числа или ещё каким-то особенным способом). Эти операции проводятся над входными данными, рассматриваемыми как набор символов, обычно, символами являются биты и байты, но возможны и другие варианты: например, слова из четырёх битов или двухбайтовые символы. Для того чтобы составить самое простое представление о современных симметричных шифрах можно представить, что шифр — это некоторый «ящик», на входы которого (в режиме зашифрования) поступают открытый текст и ключ, внутри символы открытого текста перемешиваются по схеме, определяемой ключом, и выводятся из «ящика» в качестве шифротекста. Каждый бит открытого текста оказывает существенное влияние на весь шифротекст: благодаря «лавинному эффекту» изменение даже значения одного бита в открытом тексте (или в ключе зашифрования) приводит к массовым изменениям в соответствующем шифротексте. Для расшифрования используется «ящик» на входы которого поступают шифротекст и ключ, символы опять перемешиваются, в результате на выходе получается открытый текст: если ключи совпали, то этот открытый текст совпадёт с исходным открытым текстом. Далеко не всегда для шифрования и расшифрования используется один и тот же «ящик»: алгоритмы могут различаться. Более того, в современных схемах использования, шифр может применяться только в режиме зашифрования, каким бы странным этот момент не казался на первый взгляд.

Ключом в массовых современных симметричных криптосистемах является целое число достаточно большой разрядности ― 128 бит и более. Если криптосистема добротная, то есть, наилучшим алгоритмом атаки (взлома) для неё является полный перебор всего множества ключей, то 128 бит — более чем достаточная степень безопасности. Предположим, что ключ можно угадать с вероятностью 1/2, перебрав половину пространства ключей. (Вероятность 1/2 — это огромный показатель в разрезе криптографической защиты информации. Криптосистема, которую можно взломать с такой вероятностью, никакой стойкостью не обладает.) Тогда, в случае 128-битного ключа, придётся выполнить (2 128 )/2 = 2 127 операций. Это огромное количество вариантов, перебрать их за обозримое время невозможно. Проблема состоит в том, что для шифров обычно известны оптимизации, которые позволяют уменьшить число перебираемых вариантов. Например, снизить его для 128-битного ключа до 2 46 . Перебрать 2 46 вариантов для вычислительно незатратного шифра можно очень быстро, даже если использовать в качестве вычислителя кластер из устаревших смартфонов или GPU-ферму с несколькими видеокартами. Наличие такой оптимизации является уязвимостью криптосистемы.

Шифры принято делить на блочные и потоковые. В настоящее время такое деление оказывается довольно условным и имеет, скорее, историческое значение. Блочные шифры отличаются от потоковых тем, что работают с блоками фиксированной длины и требуют разбиения потока байтов на такие блоки; в блочном шифре каждый байт обрабатывается в составе блока байтов (битов). Потоковые шифры, напротив, работают прямо с потоком битов (или байтов, потому что байт, вообще говоря, тоже можно считать блоком), без разбиения. Существуют режимы использования блочных шифров, которые позволяют рассматривать их, фактически, как потоковые. Классический потоковый шифр TLS — RC4, который сейчас считается устаревшим и нестойким. Классические блочные шифры: DES и 3DES, ГОСТ 28147-89. Особенностью блочных шифров является то, что они требуют использования дополнения (padding): в случае, если открытый текст не кратен размеру блока, его нужно дополнить до соответствующего числа битов. С этим аспектом связано немало уязвимостей в реализациях TLS.

Мы рассмотрим два шифра — AES и ChaCha20 (второй — несколько более подробно), эти шифры закрывают основную часть TLS-трафика в современном вебе.

Шифр AES

AES — является современным блочным шифром, повсеместно используемым в TLS. Строго говоря, AES — это название стандарта шифрования США, сам шифр называется Rijndael (произносится: «рай’н-да’л»). Rijndael выиграл конкурс, проводившийся NIST, и стал стандартом (AES) в 2002 году (сам шифр опубликован в 1998). Шифр стандартизован для использования с 128-, 192-, 256-битным ключом и 128-битным блоком.

AES строится из «раундов» (rounds) — повторных выполнений некоторого набора операций по трансформации блока данных; каждое повторение использует свой ключ. Набор ключей генерируется (разворачивается) из исходного ключа, с использованием специального алгоритма. Так, в случае 128-битного ключа (AES-128), на выходе алгоритма разворачивания ключа — 176 байт или 11 128-битных ключей для повторных трансформаций, составляющих шифр. Разворачивание ключа в AES использует циклические сдвиги ключей, подстановки и операции умножения в конечном поле. Процедура разворачивания ключа является составной частью многих шифров, её надёжность и «необратимость» оказывают огромное влияние на стойкость шифра в целом.

Шифр AES оперирует матрицами (таблицами) размером 4х4 элемента. Такая матрица как раз соответствует 16 байтам 128-битного блока: один элемент — один байт. Матрица со значениями байтов называется состоянием шифра, одна трансформация (раунд) последовательно выполняет над матрицей и её элементами несколько преобразований, после чего к матрице применяется ключ данного раунда. Результат преобразований переходит в следующий раунд, где всё повторяется, но со следующим ключом.

  • SubBytes — это подстановка байтов, использующая таблицу подстановок (S-box): байт B заменяется на значение из таблицы, адресуемое значением B. Таблица, соответственно, состоит из 256 элементов. Эта же таблица подстановок применяется и в алгоритме разворачивания ключа. Подобные табличные подстановки используются во многих шифрах (например, в российском ГОСТ 34.12-2015 «Кузнечик»). Они имеют огромное значение для обеспечения стойкости шифра, в частности, к так называемому дифференциальному криптоанализу. Подстановки приводят к тому, что изменение значения одного бита незамедлительно влияет на несколько других, соответственно разрядности подстановки;
  • ShiftRows — сдвиг строк. Это преобразование заключается в циклическом сдвиге элементов строк матрицы состояния. При этом первая строка не сдвигается, а вторая, третья и четвёртая — сдвигаются, соответственно, на один, два, три элемента (справа налево). Данное преобразование перемешивает байты между столбцами, связывая шифр в единую схему — отсутствие ShiftRows привело бы к тому, что байты столбцов подвергались бы независимым преобразованиям MixColumns (следующее преобразование);
  • MixColumns — перемешивание элементов матрицы состояния (столбцами). В MixColumns над каждым столбцом матрицы состояний, включающем, соответственно, четыре элемента, проводится линейное преобразование. Столбец умножается на заданное значение, оба операнда в данном умножении рассматриваются как элементы конечного поля. Аналогичные преобразования, приведённые к матричной форме, также используются в большом количестве других шифров: ChaCha, Camellia, Twofish и пр. А операция умножения в конечном поле является основой операции аутентификации в режиме шифрования GCM (отдельно рассмотрен ниже, в специальном разделе).

Далее операции шифра повторяются, но в AddRoundKey суммирование проводится со следующим ключом. Последний раунд не включает MixColumns. Для разной длины основного ключа AES предусматривает разное число только что описанных трансформаций (раундов): для 128-битного ключа — 10 раундов; AES-192 — 12 раундов; AES-256 — 14.

Запись AES на псевдокоде выглядит следующим образом (из документа FIPS PUB 197):

Cipher(byte in[4*Nb], byte out[4*Nb], word w[Nb*(Nr+1)]) // Nb - число столбцов в матрице состояния; // Nr - число раундов; // in, out - входная и выходная матрицы состояний; // w - поток ключей раундов. begin byte state[4,Nb] state = in AddRoundKey(state, w[0, Nb-1]) for round = 1 step 1 to Nr–1 SubBytes(state) ShiftRows(state) MixColumns(state) AddRoundKey(state, w[round*Nb, (round+1)*Nb-1]) end for SubBytes(state) ShiftRows(state) AddRoundKey(state, w[Nr*Nb, (Nr+1)*Nb-1]) out = state end

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

Если внимательно посмотреть на принципы построения операций AES, то окажется, что большая часть преобразований может быть предвычислена для всевозможных значений отдельных байтов (0-0xFF) и сохранена в таблицах, из которых значения будут извлекаться при работе алгоритма. Это основной программный метод оптимизации AES. Он же помогает составить общее представление о логике построения данного шифра: фактически, AES сводится к извлечению некоторой последовательности элементов матрицы возможных значений и сложении их при помощи XOR (то есть, по модулю 2) с входным блоком данных, при этом сама последовательность определяется используемым ключом, который разворачивается в набор ключей раундов.

Итак, блочный шифр ставит в соответствие блоку байтов открытого текста фиксированной длины и ключу шифрования — блок зашифрованных данных, той же длины. AES является самым часто используемым сейчас в TLS блочным шифром, фактически, это единственный распространённый безопасный вариант. Другие блочные шифры, с которыми можно столкнуться в практике TLS: 3DES (развитие устаревшего и нестойкого шифра DES, стандарта, предшествовавшего AES) и ChaCha20.

Шифр ChaCha20

Рассмотренный выше шифр AES является блочным шифром. Ранее в TLS/SSL широко использовался потоковый шифр RC4. Из-за обнаруженных недостатков RC4 сейчас считается недостаточно стойким и не должен использоваться. Другой вариант блочного шифра, получивший широкое распространение, это 3DES — улучшенный шифр, построенный на базе DES. В качестве современной альтернативы AES активно продвигается шифр ChaCha20, разработанный Даниэлем Бернштейном. В частности, соответствующие шифронаборы использует Google в своих браузерах и на своих интернет-сервисах. Кроме того, сейчас ChaCha20 является единственным, кроме AES, вариантом шифра, который доступен в спецификации TLS 1.3.

В основе ChaCha20 (мы рассматриваем шифр в изложении RFC 7539) лежит конструкция, эквивалентная блочному шифру. Строго говоря, шифр называется ChaCha, а ChaCha20 — это версия, использующая 20 раундов. Согласно определению, этот шифр является потоковым, но можно рассматривать ChaCha20 и как блочный шифр с «встроенным» режимом счётчика (это будет очевидно из описания шифра ниже). По сравнению с AES, ChaCha20 оказывается несколько проще по алгоритмической структуре и составу операций. Он алгоритмически ближе к «лёгким» шифрам, предназначенным для микроконтроллеров и других «встроенных» применений (например, Speck), что позволяет получить достаточно быстрые, безопасные и легко портируемые чисто программные реализации на разном аппаратном обеспечении. AES, действительно, отличается тем, что реализация с высокой производительностью на архитектурах, не имеющих достаточного объёма памяти и ряда специальных команд, сталкивается с серьёзными трудностями. Однако основной причиной появления ChaCha20 в стандартах и программном обеспечении TLS является необходимость наличия какой-то сравнимой по качеству альтернативы AES, так как единственность шифра ставит под угрозу безопасность протокола: в случае, если в AES будут обнаружены критические дефекты, быстро перейти окажется не на что.

Операции, составляющие шифр ChaCha20, можно разбить на три части. Первая часть, базовая, это функция ChaCha для «четверть-раунда» (Quarter Round, далее QR). Название обусловлено тем, что в раундах шифра данная функция за один вызов преобразует четыре переменные состояния из шестнадцати (16/4 = 4), а в каждом раунде — данная функция вызывается восемь раз: по четыре раза в каждой из двух конфигураций (см. ниже).

Вторая часть — функция преобразования состояния (базового блока): эта функция (далее — BF, от Block Function) построена на последовательном преобразовании состояния шифра при помощи QR-функции. Начальное состояние формируется на основе ключа, вектора инициализации (уникального значения, nonce) и счётчика, а результатом является блок ключевого потока длинной в 64 байта.

Часть три — это, собственно, функция зашифрования: вызывает функцию шифрования блока (BF) с заданным ключом и nonce, последовательно увеличивая значения счётчика, а вычисляемый таким образом ключевой поток (гамму) суммирует с открытым текстом при помощи XOR. На вход поступают: 256-битный ключ (существуют версии шифра с другой разрядностью ключей, но для TLS рекомендован именно 256-битный); вектор инициализации (96 бит); начальное значение 32-битного счётчика; поток открытого текста. На выходе — шифротекст. Шифр ChaCha представляет собой вариант режима счётчика с гаммированием, то есть, каждый бит открытого текста складывается по модулую два с соответствующим битом последовательности, которую выводит шифр. Поэтому расшифрование производится аналогично зашифрованию (вместо открытого текста — шифротекст).

Состояние шифра. Все операции шифра производятся над таблицей, задающей его состояние (это напоминает AES). Таблица состоит из 16 32-битных значений (переменных состояния), которые нумеруются естественным образом — 0..15:

00 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15

Представление в виде таблицы из четырёх строк удобно по той причине, что элементарные преобразования шифра разделены на два типа: диагональные и вертикальные (по столбцу таблицы). Начальное состояние шифра определяется значениями, которые записываются в эту таблицу. Константы, заданные в описании шифра, — записываются в первую, верхнюю, строку таблицы; значения текущего ключа — записываются в две следующих строки (256/32 = 8); значение счётчика и nonce — последняя строка:

cccccccc cccccccc cccccccc cccccccc kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk kkkkkkkk bbbbbbbb nnnnnnnn nnnnnnnn nnnnnnnn с - константы; k - ключ; b - счётчик блоков; n - nonce.

Функция «четверть-раунда» — QR. Функция преобразует четыре входных 32-битных значения (a, b, c, d) при помощи простейших базовых операций: сложение по модулю 2 32 , XOR, циклический битовый сдвиг. Используются следующие преобразования (+ — сложение; ⊕ — XOR; ⪡ N — обозначает циклический битовый сдвиг влево на N битовых позиций):

1) a = a + b; d = d ⊕ a; d ⪡ 16; 2) c = c + d; b = b ⊕ c; b ⪡ 12; 3) a = a + b; d = d ⊕ a; d ⪡ 8; 4) c = c + d; b = b ⊕ c; b ⪡ 7;

То есть, биты аргументов перемешиваются, результат записывается в те же переменные. Обратите внимание, что данная функция не зависит ни от ключа, ни от счётчика — она предназначена только для перемешивания значений состояния шифра.

Пример реализации QR на псевдокоде:

func QR(a, b, c, d)

Функция преобразования блока — BF. Данная функция вызывает QR(a, b, c, d), подставляя в качестве аргументов различные наборы переменных из таблицы состояния шифра. Четыре набора соответствуют вертикальному раунду, четыре — диагональному. Пример выбора столбца для четверти вертикального раунда:

00 [01] 02 03 04 [05] 06 07 08 [09] 10 11 12 [13] 14 15

Четверть диагонального раунда:

00 01 [02] 03 04 05 06 [07] [08] 09 10 11 12 [13] 14 15

То есть, вертикальный раунд последовательно обрабатывает четыре столбца, перемешивая значения внутри них, а диагональный — обеспечивает перемешивание между столбцами (комбинаторно, схема аналогична AES). Диагональные раунды чередуются с вертикальными, всего выполняется 10 повторов, состоящих из вертикального и диагонального раунда, что и даёт в сумме 20 раундов. После выполнения 20 раундов, исходное (на момент вызова функции BF) состояние шифра суммируется (mod 2 32 ) с полученным, сумма — выводится как результат функции BF. Наборы (по номерам) переменных состояния шифра, используемые в каждом раунде:

Вертикальные: < 00, 04, 08, 12 > < 01, 05, 09, 13 > < 02, 06, 10, 14 > < 03, 07, 11, 15 >Диагональные: < 00, 05, 10, 15 > < 01, 06, 11, 12 > < 02, 07, 08, 13 >

Пример реализации функции BF на псевдокоде:

Block(state) < var back_state = state for i := 0; i < 10; i++ < state[0], state[4], state[8], state[12] = QR(state[0], state[4], state[8], state[12]) state[1], state[5], state[9], state[13] = QR(state[1], state[5], state[9], state[13]) state[2], state[6], state[10], state[14] = QR(state[2], state[6], state[10], state[14]) state[3], state[7], state[11], state[15] = QR(state[3], state[7], state[11], state[15]) state[0], state[5], state[10], state[15] = QR(state[0], state[5], state[10], state[15]) state[1], state[6], state[11], state[12] = QR(state[1], state[6], state[11], state[12]) state[2], state[7], state[8], state[13] = QR(state[2], state[7], state[8], state[13]) state[3], state[4], state[9], state[14] = QR(state[3], state[4], state[9], state[14]) >state = state + back_state return state >

Таким образом, BF представляет собой блочный шифр, с разрядностью блока 512 бит — соответствует разрядности записи состояния шифра (16 * 32). Реализация, собственно, потокового шифрования ChaCha20 выполняется с применением режима счётчика: последовательно вызывается функция BF, с действующим ключом, действующим значением nonce и значением счётчика, которое для следующего вызова увеличивается (обычно, на единицу). Шифр инициализируется начальным состоянием, и это состояние последовательно изменяется с каждым вызовом BF. Результат работы BF каждый раз выдаёт 64 байта ключевого потока (гаммы), эти байты суммируются функцией зашифрования (XOR) с открытым текстом. Так как длина открытого текста может не быть кратной 64 байтам, для преобразования остатка, аналогично другим реализациям гаммирования в режиме счётчика, используется только часть финального блока ключевого потока (< 64). Режимы шифрования, в том числе, режим счётчика, подробно описаны ниже.

В TLS шифр ChaCha20 используется в режиме аутентифицированного шифрования, основанного на алгоритме Poly1305, также разработанном Бернштейном. Схема в основных чертах напоминает аутентификацию режима GCM, и также позволяет передавать часть данных в открытом виде (с гарантией целостности).

Режимы шифрования

Если длина открытого текста превышает длину блока, то открытый текст для зашифрования блочным шифром потребуется разделить на отдельные фрагменты, соответствующие разрядности шифра. Наивный способ использования блочного шифра «в лоб» состоит в прямом шифровании блоков открытого текста, с тем, чтобы получить шифротекст: C = E(K,PT), где PT — блок открытого текста сообщения; K — ключ; E() — алгоритм блочного шифра; С — шифротекст. Способ использования шифра называют «режимом шифрования». Только что описанный наивный вариант называется режимом ECB — Electronic CodeBook.

На практике такой способ применять нельзя, так как он не обладает стойкостью. Дело в том, что идентичные сообщения будут порождать идентичные блоки шифротекста, что приводит к утечке информации об исходном потоке данных. В частности, ECB не скрывает статистические свойства потока. Особенно плохо дела обстоят, если в защищаемом потоке присутствуют структуры, кратные размеру блока. Поэтому на практике в TLS сейчас используются другие режимы.

Режим CBC. CBC обозначает Cipher Block Chaining — в данном режиме зашифрованный блок подаётся на вход следующего шага и суммируется со следующим блоком открытого текста при помощи XOR, результат операции XOR зашифровывается, и так далее. То есть, Cn = E(K,PTn⊕Cn-1). Блоки оказываются соединены в цепочку. В качестве первого значения используется вектор инициализации, заданный в параметрах криптосистемы. Схематично данный режим можно представить следующим образом (данные на схеме преобразуются сверху вниз, от блоков открытого текста к блокам шифротекста; IV — вектор инициализации; PTn — блоки открытого текста, представляющие открытый поток; X — операция XOR; E — шифр):

PT1 PT2 PT3 | | | IV-->X /--->X /--->X | / | / | K-->E--/ K-->E--/ K-->E . | | | С1 С2 С3

Расшифрование использует обратный алгоритм шифра и обратную схему следования блоков. При этом, если для зашифрования следующего блока нужно знать результат зашифрования предыдущего, что диктует последовательную работу функции зашифрования, то для расшифрования произвольного блока достаточно знать значение шифротекста предыдущего: то есть, расшифрование может работать параллельно.

Режим CBC обладает важным свойством: одинаковые блоки потока открытого текста не порождают одинаковые блоки шифротекста. Схема позволяет преобразовать поток открытого текста большой длины в связанный поток зашифрованных блоков. Важное значение имеет вектор инициализации (это блок данных, соответствующий разрядности шифра): вектор может генерироваться случайно, либо в его роли может выступать некий счётчик. В общем случае, вектор не должен повторяться в паре с одним и тем же ключом и должен быть непредсказуем для третьей стороны. Скрывать вектор инициализации, вообще говоря, не требуется.

В TLS 1.0 режим CBC спроектирован так, что источником данных инициализирующего вектора для следующей TLS-записи является последний блок предыдущей. Это послужило основой для нашумевшей атаки BEAST. (Первый вектор инициализации генерируется в TLS 1.0 в рамках создания криптографического контекста и не передаётся между узлами, то есть, остаётся секретным, что, впрочем, не особенно увеличивает степень безопасности протокола.) В TLS 1.1 ситуация изменилась: исходные данные для вектора инициализации передаются вместе с зашифрованной записью и периодически изменяются (между записями), сам вектор для очередной итерации вычисляется по специальному алгоритму, который призван затруднить установление корреляции между значением вектора и другими параметрами, которыми могла бы манипулировать третья сторона. В TLS 1.2 вектор инициализации режима CBC передаётся в открытом виде, в самом начале зашифрованной TLS-записи.

Другим подходящим режимом работы блочного шифра является режим счётчика (CTR). В этом режиме функция зашифрования применяется не к блоку открытого текста, а к значению некоторого счётчика. Блок открытого текста суммируется с полученным шифротекстом. То есть: Cn = E(K,Ln)⊕PTn, где Ln — блок счётчика, значение этого блока своё для каждой операции зашифрования, обычно, оно просто увеличивается на единицу для каждого следующего блока. Начальное значение задаётся вектором инициализации. Счётчик не должен повторяться с одним и тем же ключом. Схема работы в режиме счётчика:

L1------>L2------>L3 | | | K-->E K-->E K-->E | | | PT1-->X PT1-->X PT1-->X . | | | C1 C2 C3

Блочный шифр, таким образом, превращается в потоковый: функция зашифрования, будучи применённой к счётчику, порождает ключевой поток (гамму), с которой суммируется открытый текст. То есть, шифр здесь используется в качестве источника псевдослучайной последовательности, которая задаётся начальным значением счётчика L и ключом шифрования. Если предположить, что ключевая последовательность случайна, то получаем схему, которая эквивалентна шифру Вернама. Добротный блочный шифр выдаёт результат, который по статистическим характеристикам должен быть вычислительно неотличим от действительно случайной последовательности.

Для расшифрования в режиме счётчика применяется та же схема, только блоки шифротекста и открытого текста меняются местами. То есть, для зашифрования — вычисляется значение XOR от результата зашифрования блока счётчика и блока открытого текста. Для расшифрования — XOR от результата зашифрования блока счётчика и блока шифротекста. Обратите внимание: сам шифр используется только для зашифрования, обратная операция не требуется. Кроме того, в общем случае, не требуется и никакого дополнения последнего блока — лишние байты просто отбрасываются. Режим счётчика — очень эффективен. В TLS, впрочем, сейчас массово применяется развитие данного режима — режим GCM, включающий также и процедуру аутентификации данных.

Коды аутентификации сообщений

В русскоязычной литературе MAC (Message authentication code — код аутентификации сообщения) называется также имитовставкой. Предназначение MAC — предоставить механизм проверки целостности сообщения, то есть, защитить данные от подмены. В общем случае, код аутентификации — это некоторое значение, вычисляемое для заданного сообщения и (обычно) секретного ключа; значение различается для разных сообщений. Чтобы вычислить корректное значение MAC — требуется знать секретный ключ. Таким образом, если сообщение было изменено третьей стороной, то проверка MAC позволит это выявить. Кроме того, корректное значение MAC позволяет утверждать, что данное сообщение было сгенерировано стороной, которой известен соответствующий ключ. Другими словами — предполагается, что подделка MAC без знания секретного ключа вычислительно недостижима. В TLS — MAC, в той или иной форме, содержится во всех зашифрованных записях. Способ вычисления кода аутентификации зависит от используемого шифронабора и режима шифрования.

HMAC — MAC, основанный на криптографической хеш-функции; используется, например, с шифрами TLS в режиме CBC. HMAC вычисляется независимо от функции зашифрования. Более того, как отмечено выше, в TLS MAC изначально использовался неверно: сперва для открытого текста вычислялся HMAC, а потом сообщение, с присоединённым кодом аутентификации, зашифровывалось. Именно так работает режим CBC в TLS. Внутри записи защищённые данные размещаются вместе с кодом аутентификации, и то, и другое — зашифровано. Архитектурная проблема состоит в том, что MAC можно проверить только после расшифрования сообщения и, если значение оказалось некорректным, реализация TLS должна сообщить об ошибке, из-за этого активный атакующий, манипулируя зашифрованным текстом, может использовать расшифровывающий узел в качестве криптографического оракула, который постепенно раскроет весь секретный текст. На этом основано несколько практических атак на TLS.

В TLS 1.0 (согласно RFC 2246) HMAC вычисляется на основе хеш-функции, согласованной в криптографическом контексте, например, SHA-1. Значение HMAC — это результат применения хеш-функции к сообщению, в которое «подмешано» значение ключа: H(K⊕Pad1+H(K⊕Pad2+text)), где H — хеш-функция, Padn — константы, K — секрет, text — исходное сообщение, + — конкатенация. Логика построения HMAC в TLS следующая:

HMAC = Hmac(Key, N + Type + Ver + Len + PT); Здесь: Hmac(Key,Content) - хеш-функция, например SHA-1, используемая в режиме HMAC; Key - секрет, согласованный сторонами для MAC в криптографическом контексте сессии; N - порядковый номер TLS-записи; Type и Ver - тип записи и версия протокола; Len - длина данных записи; PT - содержание записи; + - обозначает конкатенацию.

Таким образом, код аутентификации HMAC зависит от всех полей, определяющих свойства TLS-записи, а не только от полезной нагрузки. При этом ряд полей (N, Type, Ver) — передаются в открытом виде.

Под влиянием множества различных атак, концепция аутентификации защищаемых криптографическими методами данных эволюционировала. Современным подходом (применительно к блочным шифрам) считается использование шифра в режиме счётчика, объединяющем процесс зашифрования и вычисления MAC. При этом в область действия MAC попадают и данные сообщения, передаваемые в открытом виде. Такие режимы аутентифицированного шифрования называются AEAD — Authenticated Encryption with Associated Data (аутентифицированное шифрование со связанными данными). Фактически, массово в TLS сейчас используется единственный такой режим: GCM — Galois/Counter Mode: режим счётчика с аутентификацией Галуа. Этот режим повсеместно встречается вместе с шифром AES. Второй встречающийся вариант — Poly1305, который применяется в сервисах Google вместе с шифром ChaCha20 (см. выше). В TLS 1.3 разрешены только AEAD-режимы.

Аутентифицированное шифрование — GCM и CCM

Режим GCM (режим счётчика с аутентификацией Галуа) похож на обычный режим CTR тем, что порождает ключевой поток при помощи шифрования блоков со значением счётчика. Полученные шифротексты складываются с открытым текстом при помощи XOR. GCM строится на двух специальных операциях: incr и Mult. Первая операция вычисляет значение следующего блока счётчика по предыдущему. Вторая (Mult) — выполняет умножение в заданном конечном поле (конечные поля также нередко называют полями Галуа, откуда и происходит обозначение режима).

Блок шифротекста вычисляется так: C = E(K,L)⊕PT. Но GCM включает ещё и алгоритм аутентификации. Фактически, incr и Mult образуют два уровня GCM: первый уровень (incr) задаёт исходную гамму, ключевой поток, который позволяет зашифровать данные, второй уровень (Mult) — связывает получившиеся блоки шифротекста, действуя подобно хеш-функции, и позволяет построить код аутентификации (AuthTag в терминологии GCM). Схема работы следующая (IV — инициализирующий вектор; Ln — блоки счётчика; K — ключ шифрования; PTn — блоки открытого текста; Сn — блоки шифротекста; A — связанные данные, передаются в открытом виде; E — шифр; incr, Mult_H — функции режима GCM, Mult_H — использует секретный ключ хеш-функции H; (Bits_num) — конкатенация записей полных длин PT и A в битах; X — операция XOR):

(IV-->) L0--->incr--->L1--->incr--->L2--->incr--->L3 -->Ln | | | | | -\ v v v v v | K-->E K-->E K-->E K-->E . K-->E | | | | | . | = GCTR | v v v . v | | PT1-->X PT2-->X PT3-->X . PTn-->X | | | | | . | / | v v v . v -/ | C1 C2 C3 . Cn | | | | | | v v v v | A->Mult_H-->X /----->X /----->X . --->X -\ | | / | / | | | | v / v / v / v | | Mult_H--/ Mult_H--/ Mult_H--/ Mult_H | | | = GHASH_H | (Bits_num)->X | | | | | v | | Mult_H -/ | | \------------------------------------------------------->X | AuthTag

Блоки открытого текста суммируются (XOR) с ключевым потоком, что даёт блоки шифротекста. Эти блоки формируют входные данные функции Mult, которая, в итоге, замыкает всю конструкцию, включая открытую часть сообщения (связанные данные A), и вычисляет код аутентификации (AuthTag). Обратите внимание, что в алгоритме вычисления AuthTag также учитывается длина сообщения. Для работы Mult нужен секретный ключ H, который вычисляется путём зашифрования нулевого блока (блока, состоящего из байтов со значением 0).

В правой части схемы обозначены два условных уровня, соответствующих базовым функциям GCM: GCTR — это, фактически, режим счётчика; GHASH — это специальная хеш-функция с ключом, предназначенная для вычисления кода аутентификации. Как указано выше, основа GCTR — операция incr (или incs в стандарте NIST). Данная операция устроена достаточно просто: она увеличивает на единицу заданное количество (s) младших битов блока счётчика, рассматривая данные биты как двоичное представление целого неотрицательного числа (>=0), старшие биты остаются нетронутыми. GHASH основана на умножении значений (битовых блоков) в конечном поле (разрядность которого соответствует разрядности GCM — 128 бит).

Для работы GCM требуется инициализирующий вектор IV, этот вектор представляет собой число, используемое с данным ключом только один раз (то есть, это nonce) — строго говоря, стандарт требует, чтобы вероятность повторного использования на разных входных данных не превышала 2 -32 . Таким образом, на входе — вектор инициализации IV, секретный ключ K, открытый текст PT, связанные данные A. На выходе — шифротекст C и код аутентификации AuthTag.

Перед расшифрованием должен быть проверен код аутентификации. Проверка возможна, так как алгоритм вычисления кода использует только открытую часть защищённого сообщения: шифротекст и связанные данные. Для проверки необходимо знать секретный ключ. Если проверка прошла успешно, то расшифрование данных производится аналогично режиму счётчика — генерируется ключевой поток и, при помощи XOR, вычисляется открытый текст. При этом код аутентификации проверяется до попытки расшифрования. Результатом работы функции расшифрования может быть либо открытый текст, либо символ FAIL (⊥), обозначающий невозможность расшифрования.

Режим GCM может быть использован с любым блочным шифром подходящей разрядности блока (128 бит, в действующем стандарте). Однако в современном Интернете этот режим в большинстве случаев встречается вместе с шифром AES, в составе шифронаборов AES_GCM. Необходимо ещё раз отметить, что в AES возможны разные длины ключей (128,192,256 бит), но разрядность блока всё равно остаётся равной 128 битам.

Режим шифрования CCM. В спецификацию TLS 1.3 включены шифронаборы, использующие AES в режиме CCM (полное название: Counter with Cipher Block Chaining-Message Authentication Code). Этот режим аутентифицированного шифрования решает те же задачи, что и режим GCM, однако существенно отличается от последнего алгоритмически. CCM используется не только в TLS, и не только в версии 1.3 протокола. Так же как и в GCM, в режиме CCM блочный шифр используется только в режиме зашифрования. CCM стандартизован лишь для блочных шифров, имеющих длину блока 128 бит.

Режим CCM представляет собой комбинацию из схемы аутентификации сообщений CMAC и режима счётчика. Используемая схема вычисления кода аутентификации построена аналогично режиму шифрования CBC (см. выше), отличие состоит в том, что промежуточные блоки шифротекста используются только для вычисления следующего блока, а в качестве значения MAC — используется значение последнего блока. CCM предусматривает, что часть сообщения может передаваться в открытом виде. Открытая часть защищена от подмены данных кодом аутентификации. Как будет видно из схемы, приведённой ниже, основной особенностью CCM является то, что данный режим строго разделяет процессы вычисления кода аутентификации и зашифрования, причём код аутентификации вычисляется для открытого текста, а на следующем этапе зашифровывается. Для проверки целостности данных принимающей стороне придётся сперва расшифровать полученные данные. Это означает, что внутри режима шифрования CCM используется схема, в которой код аутентификации не защищает зашифрованные данные, а сам преобразуется функцией зашифрования (получаем MAC-then-encrypt). В GCM код аутентификации вычисляется для зашифрованных данных (естественно, включая открытую часть AEAD), и проверка целостности сообщения возможна до запуска процедуры расшифрования. Такой подход позволяет избавиться от некоторых векторов атак. Режим CCM рекомендован для TLS 1.3, однако поддерживается далеко не везде. (Исторически, одной из основных причин включения CCM в спецификацию является его возможное использование устройствами, которые не имеют аппаратной поддержки функций GCM; другая важная причина — CCM присутствует в спецификациях протоколов беспроводной передачи данных WiFi.)

Итак, рассмотрим режим CCM в соответствии с документом NIST SP 800-38C. Использование в TLS отличается в некоторых деталях (например, определение инициализирующих значений и пр.), однако логика построения — идентична. В абстракции CCM используются две функции: F() и Cntr(). Функция F() предназначена для преобразования исходных данных. F() получает в качестве аргументов открытый текст (далее — PT), который будет зашифрован, дополнительные данные (A), передаваемые в открытом виде, а также инициализирующее значение (nonce, N). Результатом этой функции является последовательность битовых блоков B0, B1, B2. далее преобразуемая в соответствии со схемой для вычисления кода аутентификации. Фактически, F() просто собирает входные данные в один битовый массив, делит его на блоки нужной разрядности, вычисляет длины и параметры, которые записывает в нулевой (начальный, так как используется сетевой порядок) блок B0. Блок B0 играет служебную роль и содержит значения, определяющие представление данных в полном сообщении. Например, в этом блоке, с помощью битовых флагов, определяется присутствуют ли дополнительные открытые данные в сообщении, какую длину имеет запись кода аутентификации и т.д. Важным моментом является то, что в B0 записывается значение nonce, при этом блок B0, как видно из схемы, используется для инициализации схемы CMAC, то есть, в процессе вычисления кода аутентификации.

Функция Cntr() реализует работу счётчика и генерирует последовательность блоков L0, L1. которые поступают на вход, собственно, шифра, а после зашифрования — суммируются с блоками открытого текста при помощи XOR. Как и в режиме CTR блоки счётчика представляют собой битовые блоки с уникальными значениями, которые вычисляются на основе nonce (подходит и простейший вариант, где значение просто увеличивается на единицу). При этом первый (слева) байт каждого блока счётчика в CCM также содержит дополнительные флаги (аналогично B0).

Работа CCM показана на схеме (A — дополнительные данные, передаваемые в открытом виде; PT, PTn — открытый текст сообщения (зашифровывается), блоки открытого текста; N — инициализирующее значение; B0. Bn — блоки сообщения; L0. Ln — блоки счётчика; K — симметричный секретный ключ; E — функция зашифрования; X — XOR; Tag — код аутентификации; Сn — блоки шифротекста):

N, A, PT = F(N,A,PT) = Cntr() A---->F(N,A,PT)--------------- . -- | \ \ \ \ -\ | B1 B2 B3 . Bn | | | | | | | | B0-->X /--->X /--->X . ->X | CMAC | | / | / | | | | K-->E--/ K-->E--/ K-->E . K-->E--->Tag | | | -/ | |-----------------------------------------/ | | | | L0 L1------>L2------>L3 -\ | | | | | | | | | K-->E K-->E K-->E K-->E | | | | | | | | CTR | \------>X PT0-->X PT1-->X PT2-->X . | | | | | | | [A0. An] \ [C0 C2 C3 Cn] | \ | -/ \--------------------------------/ Схема зашифрования в режиме CCM.

Таким образом, на первом этапе битовые блоки (Bn), полученные из входного сообщения, преобразуются в код аутентификации. Преобразования совпадают с режимом CBC. Вычисленный код аутентификации (Tag) зашифровывается при помощи сложения с результатом зашифрования начального блока счётчика (L0) и присоединяется в конец шифротекста (Cn). Часть сообщения, подлежащая зашифрованию (PT), суммируется с зашифрованными значениями остальных блоков счётчика и присоединяется к дополнительным данным (A), которые разбиваются на блоки (в том числе, с использованием дополнения, которое требуется для выравнивания длины).

Защищённые записи TLS

Защищённая запись в TLS содержит полезные данные приложения, а также может содержать сообщения Handshake или Alert (в TLS 1.3). От других записей — защищённые отличаются кодом типа: 0x17 (23 в десятичной системе), ApplicationData. Полезные данные внутри записи зашифрованы действующим шифронабором, защищены отдельным кодом аутентификации (MAC) или AEAD-режимом. Часть параметров передаётся в открытом виде: тип записи, версия, длина данных и др. В TLS 1.3 подход к обработке защищённых записей сильно изменился. Так, открытый заголовок зафиксирован в качестве исторического: то есть, любая защищённая запись TLS 1.3 имеет значение поля версии 0x0303, что соответствует TLS 1.2, однако в самом протоколе 1.3 данное поле не используется. В TLS 1.3 все защищённые записи передаются с «историческим» кодом типа 0x17, при этом подлинный тип записи — содержится внутри защищённых данных.

Рассмотрим пример защищённой TLS-записи версии 1.3. Это запись, содержащая HTTP-запрос GET, адресованный хосту facebook.com и запрашивающий индексный документ. В TLS 1.3 структура защищённой записи, если рассматривать её в открытом виде, следующая: к байтам полезных данных приписан байт с кодом типа записи, следом за этим байтом могут идти нулевые байты дополнения. То есть, если после успешного расшифрования защищённых данных, последний байт оказывается нулевым, это означает, что использовано дополнение и все нулевые байты в конце нужно отбросить. В случае, если дополнения нет — последний байт корректной записи не может быть нулевым, так как он содержит код типа записи.

Смещение Байты Комментарий (десятичное) (шестнадцатеричное представление) 0000 17 ; Исторический заголовок. Код типа: 0x17 = 23 (Application Data). ; В TLS 1.3 этот тип строго зафиксирован, но не используется для ; определения типа записи. Например, запись Handshake в TLS 1.3 ; имеет тип 0x16. Если такая запись передаётся в защищённом виде, ; то в данном заголовке для неё всё равно будет указано значение 0x17. 0001 03 03 ; Историческое значение версии: 0x0303 = TLS 1.2. Значение ; строго зафиксировано и не является обозначением версии в TLS 1.3. ; Код версии TLS 1.3 - 0x0304, но в заголовке записи он не указывается, ; так как узлам действующая версия протокола известна из контекста, ; выработанного в процессе установления соединения. 0003 00 5D ; Длина данных. 0x005D = 93 байта. (Длина указывается действующая.) 0005 7E 6F B1 0F DB D3 7C E3 ; Далее идут защищённые данные. В данном случае, используется 8C 0F 7A 89 F6 0B 0D D1 ; шифр AES в режиме GCM. При зашифровании, заголовок сообщения был 24 91 58 EC D0 B7 BE 85 ; присоединён (слева) к защищаемым данным в качестве "связанных данных", 10 9C AC CC 9A 70 08 99 ; что соответствует и схеме AEAD GCM, и логике построения TLS-записи. 55 D2 5D 93 6D 3F 20 91 ; Таким образом, данные заголовка передаются в открытом виде, но защищены 26 F4 A2 02 27 74 2C 57 ; кодом аутентификации. AE B9 CC F2 6A E5 8B 5A ; Длина блока защищённых данных больше, чем длина исходных данных (ниже). F3 14 CE AD C4 46 42 3D ; Это объясняется тем, что к результату зашифрования приписывается код 52 8F 58 37 9E D8 EA 77 ; аутентификации GCM, имеющий длину 128 бит, что составляет 16 байтов. 30 D2 0B B3 77 30 DE 36 FD 2C 79 FA EA 65 DF F0 22 6C A3 3B 08 === Исходные данные, в открытом виде: 47 45 54 20 2F 20 48 54 54 50 2F 31 2E 31 0D 0A ; GET / HTTP/1.1\r\n 48 6F 73 74 3A 20 66 61 63 65 62 6F 6F 6B 2E 63 6F 6D 0D 0A ; Host: facebook.com\r\n 55 73 65 72 2D 41 67 65 6E 74 3A 20 54 4C 53 2D 62 6F 74 2F ; User-Agent: TLS-bot/ 30 2E 32 20 54 4C 53 2D 31 2E 33 ; 0.2 TLS-1.3 0D 0A 0D 0A ; \r\n\r\n 17 ; Тип записи (актуальный код) 0x17 = 23. 00 00 00 00 00 ; Дополнение: пять нулевых байтов.

Длины ключей и сочетание криптосистем

С шифронаборами в TLS связано несколько криптографических примитивов, к которым применимо понятие разрядности. Возьмём в качестве примера шифронабор TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 — здесь есть разрядность ключа RSA (рекомендуемое значение — 2048 бит или более); разрядность симметричного ключа AES (указано 128 бит) и, наименее важная, разрядность хеш-функции (256 бит). Есть ряд рекомендаций по выбору разрядности ключей для криптосистем в TLS. Так, максимальная степень защиты должна применяться к сеансовым данным, потому что ради их защиты TLS и используется. Эти данные защищает симметричный шифр. 256 бит для AES считаются достаточными. Большие длины ключей для добротного симметричного алгоритма не имеют никакого смысла. В качестве симметричного шифра может служить не только AES, но и CAMELLIA, и даже корейский шифр ARIA. Возможно и использование шифров ГОСТ для TLS, если они поддерживаются программной реализацией (см. Приложение В).

Криптосистемы с открытым ключом служат в TLS для аутентификации. Заметьте, что задача выработки общего секрета — эквивалентна аутентификации узла, с которым устанавливается соединение. Действительно, при использовании слабого ключа аутентификации, атакующая сторона может перехватить сессию, выдав себя за сервер (например). Однако на практике это означает проведение сложной активной атаки, которая представляет собой менее вероятную угрозу, чем простое прослушивание канала, от которого защищает симметричный шифр. Естественно, перехвативший сессию атакующий уже не будет испытывать проблем со взломом симметричного шифра. Тем не менее, защита процедуры аутентификации нередко перемещается на второе по важности место, после защиты потока данных.

Хорошим примером, почему это происходит, является следующее наблюдение (подсказанное Z.T. в комментариях на dxdt.ru): если вы используете нестойкий алгоритм для аутентификации узла, то, в обозримой перспективе, например, через десять лет, этот алгоритм может быть взломан; взломавшая алгоритм сторона получает возможность подделывать сессии, но как атаковать сессию десятилетней давности? Никак. А вот если взломан шифр, защищающий передаваемый трафик, то становится возможным прочитать трафик, записанный десять лет назад. В этом может быть смысл, так как трафик, возможно, содержит до сих пор актуальные сведения.

Весьма полезной практикой является разумное выравнивание стойкости используемых криптосистем. Например, в подавляющем большинстве случаев не имеет смысла использовать RSA-ключ длиной в 4096-бит, если ваш TLS-сервер всё ещё поддерживает SSLv3, а в качестве симметричного шифра применяет DES с 56-битным ключом.

Основные направления атак на TLS

TLS имеет дефекты на уровне протокола, но гораздо больше дефектов обнаруживается в его реализациях. Например, до сих пор можно нередко встретить поддержку заведомо нестойких, устаревших шифронаборов, использующих ключи длиной менее 128 бит. В 2016 году началась активная миграция в сторону стойких сочетаний ключей и шифров в области HTTPS. Но проблема устаревших и слабых криптографических параметров остаётся актуальной для «мобильных приложений» (приложений, предназначенных для смартфонов) и многих видов встроенного программного обеспечения, которое не обновляется. Встречается даже поддержка SSLv2, который давно не является хоть сколь-нибудь защищённым на практике. Использование устаревших протоколов и шифронаборов означает, что атакующий может провести понижение уровня защиты до шифра, который сможет взломать на лету, после чего подделает сообщения Finished, став, тем самым, посредником в сессии. (Посредник в TLS может прослушивать весь трафик.) Однако современные браузеры не позволяют использовать заведомо нестойкие сочетания криптосистем и не поддерживают устаревшие версии SSL/TLS, что сводит поверхность атаки к минимуму. Тем не менее, неверно было бы считать, что проблем здесь нет: существует большое число устаревших клиентских устройств, которые всё ещё поддерживают старые протоколы, по историческим причинам среди них немало важных узлов, это, например, домашние WiFi-роутеры.

Выше уже упоминалась необходимость дополнения данных при использовании блочных шифров, которая приводит к появлению нежелательных криптографических оракулов (такой оракул помогает «угадывать» секретные тексты). Есть целый класс оракулов, — которые в англоязычной литературе называются Padding oracle, — породивший несколько нашумевших атак. Одно из первых использований оракула, связанного с дополнением данных, относится к 2003 году. Атака, сконструированная Сержем Воденэ (Serge Vaudenay), основывалась на том факте, что реализация протокола SSL возвращала разные сообщения об ошибках в зависимости от того, удалось ли после расшифровки записи обнаружить корректное дополнение, но не совпал код аутентификации (MAC), или корректного дополнения данных обнаружить не удалось. Именно последствия этой атаки были устранены только спустя семь лет в веб-сервере IIS. Не останавливаясь на только что упомянутой атаке, рассмотрим подробнее это важное направление.

Код аутентификации представляет собой некоторое число, записанное в виде последовательности байтов, которые прикрепляются к защищаемым TLS данным. Принимающая сторона вычисляет значение кода аутентификации для принятых данных и сравнивает его с прикреплённым кодом. Если значения совпали, то делается вывод о неизменности данных, если не совпали, то данные должны быть отброшены. Дополнение сообщения (padding) также входит в набор данных, для которого осуществляется вычисление кода аутентификации. В добротной системе — внешняя сторона не должна иметь инструмента, который позволяет различить результаты обработки сообщений, кроме разделения на принятые и отвергнутые. Если же утекает дополнительная информация о внутреннем состоянии реализации криптосистемы, то оказывается возможным создание оракула, который позволит при помощи простого перебора раскрыть либо какую-то часть защищаемого сообщения, либо восстановить его полностью.

В качестве иллюстрации, рассмотрим гипотетическую схему, которая концептуально схожа с реализациями, послужившими источником уязвимостей TLS/SSL — POODLE, BEAST, SWEET32 и др. Пусть в нашей теоретической криптосистеме блочный шифр работает в режиме CBC и используется следующий алгоритм дополнения до полного блока: в конец блока дописываются байты со значением, равным количеству байтов в дополнении. То есть, если требуется дописать три байта, то все три байта имеют значение 03. Если блок дополняется пятью байтами, то со значением 05, и так далее. Дополнение вносится в открытый текст, перед зашифрованием. На стороне получателя проверяются значения всех байтов дополнения, начиная с самого последнего байта (мы не рассматриваем способ получения принимающей стороной информации о длине дополнения).

При расшифровании в режиме CBC выполняется операция XOR предыдущего блока шифротекста со значением, полученным в результате расшифрования текущего блока (само это значение ещё не является открытым текстом). На схеме это выглядит следующим образом:

C1 C2 C3 | | | |-\ |-\ | K-->D \ K-->D \ K-->D | \ | \ | IV-->X \--->X \--->X | | | PT1 PT2 PT3

Здесь C1, . Cn — блоки шифротекста; PTn — блоки открытого текста; IV — инициализирующий вектор; X — операция XOR; K — ключ расшифрования; D — алгоритм расшифрования (шифр). Дополнение содержится в последнем блоке, C3. Схема является обратной к приведённой в разделе «Режимы шифрования». Код аутентификации на схеме не показан — предположим, что код просто дописывается в конец сообщения.

Схема работы криптосистемы. Если сообщение, состоящее из набора блоков , где C3 содержит дополнение, успешно расшифровано, — то есть, после преобразования получено корректное дополнение, — криптосистема переходит к проверке кода аутентификации. Если в процессе расшифрования получено некорректное дополнение, то возвращается сообщение об ошибке расшифрования (присвоим этой ошибке обозначение PAD_ERROR), а код аутентификации не проверяется. (В случае, когда не совпал код аутентификации — возвращается другое сообщение об ошибке, пусть оно называется MAC_ERROR.) В данной схеме байты дополнения расположены в конце последнего блока. Предположим, что число этих байтов известно третьей стороне, которая проводит активную атаку. Пусть теперь дополнение состоит из одного байта, имеющего, соответственно, значение 01. Тогда последний блок открытого текста имеет следующую структуру: [01], где — последовательность байтов открытого текста, а [01] — байт дополнения до полной длины блока.

Заметим, что атакующей стороне известны все блоки шифротекста (они могут быть пассивно перехвачены из канала связи). Мы допускаем активную атаку, поэтому возможна произвольная замена блоков. Заменив блок C2 (см. схему) на произвольный блок V, а блок C3 — на некоторый полный блок шифротекста Cx, и отслеживая сообщения об ошибках, выдаваемые криптосистемой, атакующая сторона может добиться ситуации, когда результат расшифрования блока Cx и последующей операции XOR с блоком V (подменный блок) даст значение 01 в последнем байте. Это значение является результатом операции XOR последнего байта блока V и последнего байта расшифрованного блока Cx. Повторное выполнение XOR с байтом блока V и значением 01, восстанавливает последний байт из расшифрованного Cx. То есть, атакующий узнал значение последнего байта из подставленного в конец цепочки блока Cx, который может являться произвольным блоком с защищёнными данными — это ключевой момент атаки: значение последнего байта последнего блока (дополнение) и так было известно, однако замена блока на другой позволяет навязать криптосистеме задачу расшифрования блока, ни один байт которого не был известен атакующему. Пока значение последнего байта, полученного после расшифрования, не совпадало с ожидаемым значением дополнения — криптосистема выдавала ошибку PAD_ERROR, это позволяло атакующей стороне определить, что байт не угадан; как только значение совпало с 01 — криптосистема выдала ошибку MAC_ERROR, что явилось сигналом об успешном подборе. Такое поведение криптосистемы и является криптографическим оракулом. Так как целостность сообщения проверяется после того, как проведено расшифрование, становится возможной последовательная манипуляция блоками.

C1 V Cx | | | |-\ |-\ | K-->D \ K-->D \ K-->D | \ | \ | IV-->X \--->X \--->X | | | PT1 PT2 PT3

В описанной схеме, после того, как стал известен последний байт, можно, урезав фиктивное значение длины открытого текста, перейти к предпоследнему, и так далее: так как известно, какую маску нужно использовать, чтобы каждый следующий байт фиктивного дополнения соответствовал общему числу байтов в этом дополнении. Другими словами: атакующему теперь известно, какое значение имеет последний байт расшифрованного блока Cx, соответственно, он может так подобрать маску в виде подменного блока V, что результат XOR будет равен не 01, а 02, как требуется для дополнения из двух байтов (длина дополнения соответствует значению байта дополнения); соответственно, это позволяет перейти к подбору следующего байта (предпоследнего). Манипулируя длиной сообщений и значениями блоков, третья сторона может последовательно раскрыть любое количество байтов секретного текста за обозримое время: так, очевидно, что один байт будет гарантированно раскрыт за 256 попыток (максимально), а хорошая практическая вероятность около 1/2 достигается в 128 попыток.

Схема атаки, для случая с одним байтом дополнения:

(Cx) [B1][B2][B3][B4][B5][B6][B7][B8] Dec(K) [A1][A2][A3][A4][A5][A6][A7]|[TT] XOR (V) [V1][V2][V3][V4][V5][V6][V7]|[V8] = [F1][F2][F3][F4][F5][F6][F7]|[PP] [TT] = [PP] XOR [V8]

Если код аутентификации вообще не используется, то схема атаки не меняется. Однако при совпадении значения дополнения — расшифрованные данные окажутся мусорными, так как атакующая сторона проводит подмену блоков. Соответственно, приложение, использующее эти данные, может работать неверно. Тем не менее, факт отсутствия ошибки расшифрования послужит сигналом об успешном результате обработки очередного блока.

Обратите внимание, что, если атакующий может выбрать открытый текст, то данная схема уже не зависит от того, проверяет ли сервер все байты дополнения, или только последний. Этот момент используется в построении атаки POODLE.

Рассмотрим теперь как работает конкретная атака на TLS/SSL, использующая уязвимость POODLE в SSLv3 (а также в некоторых реализациях TLS 1.0). Эта уязвимость построена на описанном только что «оракуле дополнения», однако схема отличается: предполагается, что атакующий может не только переставлять блоки внутри защищённого сообщения, но и изменять часть открытого текста.

Пусть атака проводится на HTTPS-соединение, а атакующий может отправлять HTTP-запросы из браузера пользователя (например, заманив пользователя на специально подготовленную страницу, что несложно сделать, если уже есть возможность модификации трафика). Целью атакующего является получение содержимого файлов cookie, адресованных защищённому веб-ресурсу. В этом случае, POST-запросу, отправляемому на адрес защищённого HTTPS-ресурса, — работающего по протоколу SSLv3 с шифронабором, использующим режим CBC, — будет соответствовать несколько блоков шифротекста. Cookie-файл передаётся в этой же цепочке блоков, и, согласно протоколу HTTP, следует после адреса документа (path), на который отправляется запрос POST (тут возможны отличия в деталях, но расположение блока, который интересует атакующего, так или иначе известно). Идея состоит в том, чтобы, манипулируя длинной URL в POST-запросе, сдвигать значение Cookie так, чтобы его байты последовательно оказывались на последнем месте в одном из блоков цепочки.

В SSLv3 фрагмент записи, содержащий код аутентификации сообщения (MAC) предшествует дополнению. А само дополнение может представлять собой один полный блок, при этом последний байт дополнения содержит значение, равное числу байтов дополнения. Шифротексты последовательных сообщений, содержащих генерируемые клиентом HTTP-запросы, будут различаться, как того требует протокол. В рамках атаки, блок, содержащий cookie-файл, переставляется в конец записи, на место блока с дополнением. POODLE использует в качестве оракула только последний байт, то есть — байт, в котором записана длина дополнения. Сервер, при попытке обработать данные, будет возвращать ошибку SSL в случае, если значение последнего байта блока после расшифрования не совпало с корректным (ожидаемым) значением дополнения. Если значения совпали, то сервер корректно обработает HTTP-запрос. Перебор возможен потому, что при каждом следующем запросе, с тем же открытым текстом, блоки шифротекста будут иметь другое значение (это одно из основных свойств TLS, рассмотренное выше). Для проверки следующего байта — атакующий модифицирует открытый текст, — то есть, HTTP-запрос, — таким образом, что значение cookie-файла смещается на один байт вправо (к концу записи), и на границе блока оказывается следующий байт cookie.

Видимое «снаружи» различное поведение программной реализации TLS в зависимости от того, были в TLS-записи обнаружены корректные дополнение и MAC или некорректные, — традиционный фундамент для атак, актуальный до сих пор. Эти атаки и привели к тому, что SSLv3 и более ранние версии перешли в разряд нестойких. Шифры, работающие в режиме GCM — а именно, AES, — не используют уязвимого дополнения блоков, соответственно, ликвидируют основу для возникновения оракулов такого типа (но, конечно, не избавляют от возможных оракулов полностью).

Атака под названием Sweet32 — относится к классу атак, использующих фундаментальные особенности протокола, а не уязвимости конкретных реализаций. Sweet32 так же требует работы в режиме CBC, но при этом зависит от шифра — он должен использовать 64-битные блоки (откуда название: 32=64/2). Атака основана на достаточно простом, но поэтому весьма универсальном, свойстве: так как результат работы добротного шифра должен быть вычислительно неотличим от случайного результата, в криптосистеме в какой-то момент обязательно произойдёт коллизия — возникнут два блока с одинаковыми значениями. Из-за парадокса дней рождения, вероятность такой коллизии для шифров с малой разрядностью блока становится достаточно высокой на объёмах данных, которые, по современным меркам Интернета, не являются недостижимыми. Так, для 64-битного блока граница находится около 32 гигабайт. Sweet32 и подобные атаки не требуют наличия каких-то дефектов реализации или возникновения плохо предсказуемых ошибок в криптосистеме. Причина, по которой возможны такие атаки, архитектурная.

Рассмотрим блочный шифр с 64-битным блоком, работающий в режиме CBC, с одним и тем же значением ключа. Коллизия блоков шифротекста означает, что результатом работы шифра оказались два блока с одинаковым значением. Присвоим этим блокам номера i и k: CTi == CTk. Соответственно, так как ключ не изменялся, а шифр эквивалентен перестановке битов, два блока, поступившие на вход шифра, равны между собой: INi == INk (обозначим эти блоки как IN, поскольку они, согласно режиму шифрования, не являются открытым текстом в контексте криптосистемы). Шифр работает в режиме CBC, это означает, что на вход шифра (блоки IN) поступали результаты суммирования предыдущего блока шифротекста (CTi-1, CTk-1) c соответствующими блоками открытого текста (PTi, PTk), таким образом: CTi-1⊕PTi == CTk-1⊕PTk, следовательно, по свойствам XOR: PTk⊕PTi == CTk-1⊕CTi-1. Оба блока CTk-1 и CTi-1 — известны, так как они передаются в открытом виде, поэтому прослушивающая канал сторона может вычислить значение XOR от двух блоков открытого текста. Это и составляет утечку. С вероятностью около 1/2 коллизия блоков произойдёт на выборке в 2 n/2 = 2 32 блоков (n — разрядность блока, 64 бита).

Если атакующему известно значение XOR от двух блоков открытого текста (S), а также значение одного из этих блоков, то возможно вычислить второй (PT1⊕S == PT2). В случае с HTTPS некоторые фрагменты открытого текста, действительно, известны заранее, из свойств протокола HTTP и метаданных, например: URL, некоторые файлы Cookie, заголовки запроса, части веб-страницы (её можно получить с сервера) и так далее. Авторы практической атаки Sweet32 использовали для генерации трафика Javascript-код, отправлявший большое число HTTP-запросов с известной частью открытого текста. В качестве транспорта использовалось TLS-соединение с 64-битным 3DES (шифр, основанный на стандарте DES). Целью служили cookie-файлы, дописываемые браузером (это типовой метод демонстрации осуществимости атак на HTTPS). Первая коллизия была зафиксирована при числе переданных блоков 2 31.3 , а полное раскрытие 16-байтного секрета потребовало 705 гигабайт трафика.

Данные объёмы трафика достаточно велики, несмотря на то что являются вполне достижимыми на практике. Кроме того, применительно к TLS, требуется, чтобы весь трафик передавался в рамках одного контекста сессии, так как замена ключей и векторов инициализации приведёт к тому, что атака не сработает из-за отсутствия коллизий. При этом, 705 гигабайт соответствует, приблизительно, 2 36,46 , что превышает порог 2 n/2 == 2 32 блоков, после которого должна была бы последовать замена ключей. Для шифров с большей разрядностью блока, например, AES-128, данная атака оказывается ограничена только тем фактом, что резко возрастает требуемое для достижения практической вероятности возникновения коллизии число блоков, что, естественно, не отменяет необходимости периодической замены ключей.

В описании атак, основанных на подмене блоков и байтов дополнения, отмечено, что сигналом о «правильной» интерпретации байтов дополнения могут служить различные коды ошибок, возвращаемые реализацией TLS, либо сам факт успешной обработки запроса протокола, находящегося уровнем выше TLS (HTTPS в случае с POODLE). Однако атакующий может извлечь полезную информацию и путём анализа времени обработки данных на стороне реализации TLS. На таком побочном канале утечки работает атака Lucky13. Основная идея Lucky13 состоит в отправке на сервер специальным образом подготовленных TLS-записей, содержащих тщательно подобранные дефекты. Обработка этих записей на сервере и, в частности, вычисление кода аутентификации, приводит к тому, что сообщение об ошибке поступает с различной задержкой по времени. То есть, уязвимые реализации используют один универсальный код ошибки (следовательно, не содержат оракулов, подобных описанным выше), но время генерации этого кода коррелирует с данными открытого текста, расположенного внутри TLS-записей. Построив статистику времени обработки запросов, которые были специально подготовлены, можно вычислить открытый текст. То есть, в данном случае, криптографический оракул «отвечает» атакующей стороне посредством изменения времени выполнения тех или иных операций на сервере. Подобные побочные каналы утечки являются одними из самых сложных, как в плане выявления, так и в плане противодействия.

В 2015 году появилась атака Logjam, связанная с использованием устаревших шифронаборов, а именно с протоколом Диффи-Хеллмана в так называемом «экспортном» варианте. «Экспортные» шифры относятся к первому периоду криптовойн, к 90-м годам 20 века, когда был запрещён экспорт стойкой криптографии за пределы США, а вместо стойкой — экспортировались заведомо нестойкие криптосистемы. Logjam не использует оракулов, но позволяет провести понижение уровня секретности, навязав клиенту и серверу нестойкий вариант DH, на группе малой разрядности (512 бит). Это возможно из-за архитектурного недостатка протокола: предложенные клиентом шифронаборы никак не удостоверяются, при этом клиент принимает любые параметры DH, переданные сервером, если только может их обработать. Используя сравнительно небольшие компьютерные мощности, для групп DH малой разрядности (1024 бита и меньше) возможно провести предварительные вычисления арифметической структуры, которые позволят в дальнейшем вычислять дискретный логарифм, фактически, в режиме реального времени. Соответственно, перехватывающий узел может раскрыть сеансовый ключ. (В распространённых браузерах проблема была исправлена летом 2015 года.)

Logjam использует следующую архитектурную особенность TLS: описанный выше процесс установления соединения (Handshake) в TLS версий ниже 1.3 подразумевает, что фактическая аутентификация клиентом серверных параметров криптосистемы (выбранный шифронабор и т.д.) проводится лишь в самом конце. Основой такой аутентификации является сообщение Finished, которое передаётся в защищённом виде и должно подтверждать соответствие выбранных параметров состоянию сервера. При этом дополнительной аутентификации сообщений клиента, на начальном этапе, не предусмотрено. Атакующая сторона может осуществить атаку «Человек посередине» и, например, подменить в самом начале соединения клиентское сообщение ClientHello, содержащее идентификатор выбранного сервером шифронабора.

На первый взгляд, подобные подмены не могут достичь успеха: во-первых, сервер тполучает Finished от клиента, а это сообщение содержит значение хеш-функции от всех предыдущих сообщений и удостоверено кодом аутентификации; во-вторых, ответное сообщение ServerKeyExchange содержит подпись сервера, которая может быть проверена клиентом, а перехватывающий узел не сможет поменять сессионные параметры так или иначе. Но оказывается, что как раз здесь и скрывается возможность для атаки. Дело в том, что ServerKeyExchange никак не привязано к выбранному шифронабору, это сообщение содержит лишь параметры; в случае классического протокола Диффи-Хеллмана — это задающий группу модуль и открытый ключ сервера. Ключевой момент Logjam в том, что для клиента все параметры Диффи-Хеллмана в ServerKeyExchange выглядят одинаково. То есть, достаточно, чтобы сервер выбрал шифронабор с DHE (сеансовый вариант Диффи-Хеллмана) и передал любые подходящие для атаки параметры в ServerKeyExchange.

Пусть сервер поддерживает «экспортные» варианты протокола Диффи-Хеллмана: DHE_EXPORT. Предположим, что активно перехватывающий соединение узел подменяет исходное сообщение клиента ClientHello и заменяет список шифронаборов на список, разрешающий только варианты с DHE_EXPORT. В ответ, помимо ServerHello, сервер отправляет ServerKeyExchange, содержащий параметры DHE в «экспортном» варианте, то есть, с модулем разрядностью в 512 бит. Параметры при этом подписаны серверным секретным ключом. Узел, проводящий атаку, заменяет в ServerHello выбранный шифронабор на любой вариант с DHE (уже не с «экспортным»), а на основании открытого ключа в ServerKeyExchange и параметров из ClientHello и ServerHello вычисляет сеансовый ключ. Очевидно, что, используя данный ключ, перехватывающий узел сможет подделать все прочие сообщения (кроме ServerKeyExchange). Клиент, получив в поддельном сообщении ServerHello указание на шифронабор с DHE, принимает параметры из ServerKeyExchange, так как это подлинные параметры, подписанные серверным ключом — единственная их особенность состоит в том, что используется модуль малой разрядности.

Для того, чтобы данная атака сработала, необходима поддержка DHE_EXPORT на сервере и поддержка групп DH малой разрядности клиентом. Ни то, ни другое — не является необходимым для нормальной работы TLS в современных условиях.

Другим примером атаки, использующей устаревшие экспортные ограничения против современных версий TLS, является DROWN, опубликованная в 2015-2016 годах (CVE-2016-0800). DROWN является развитием атаки Блейхенбахера (Daniel Bleichenbacher) и использует соединения по морально устаревшему протоколу SSLv2 для расшифрования сеансовых ключей, которые передаются в сессиях TLS. Для того, чтобы атака стала возможной, необходимо наличие SSLv2-сервера, использующего общий с атакуемым TLS-сервером секретный ключ RSA. Такая ситуация вполне возможна: например, один и тот же TLS-сертификат может быть установлен и на веб-сервере, и на почтовом сервере, а это, в свою очередь, требует использования общего секретного ключа. Со стороны TLS-сервера не требуется наличие каких-то уязвимостей: атака работает против корректной реализации протокола TLS. Единственное существенное ограничение: в рамках атакуемой TLS-сессии клиент и сервер должны использовать для передачи сеансового секрета статический вариант с шифрованием RSA (как описано выше, такой способ не рекомендуется, но, тем не менее, до сих пор используется, в том числе, в банковских системах дистанционного обслуживания, где такой выбор обусловлен желанием инспектировать трафик при помощи относительно простых аппаратно-программных средств и методов).

Часть атаки DROWN в отношении TLS-сервера может быть реализована пассивно: то есть, только с использованием записанного трафика (а именно — TLS Handshake). Однако для завершения атаки потребуется активный доступ к связанному SSLv2-серверу — отправка запросов, имитирующих установление соединения SSLv2.

Атака основана на особенностях установления соединения SSLv2, в варианте, использующем те же самые «экспортные» шифронаборы, которые упоминались выше. Кроме того, ключевую роль играет вариант дополнения блока данных RSA, что совпадает с описанными в начале этого раздела криптографическими оракулами, возникающими при использовании симметричных шифров и дополнения (несмотря на то, что RSA — не является симметричным шифром). Установление соединения в SSLv2 существенно отличается от TLS (как протокол, SSLv2 представляет скорее исторический интерес, поэтому мы не рассматривали его в рамках настоящего описания; кроме того, формально, SSLv2 — проприетарная технология). В SSLv2, клиент в самом начале сеанса отправляет на сервер секрет, зашифрованный с использованием открытого RSA-ключа сервера. Для выполнения экспортных ограничений предусмотрен режим, когда часть сеансового секрета передаётся в открытом виде, и только часть, соответствующая по разрядности требуемому ограничению (40 бит), зашифрована RSA. Современные вычислительные мощности, в случае с анализом «экспортного» SSLv2, позволяют очень быстро перебрать 2 40 вариантов (на практике, для DROWN, пространство перебора с целью расшифрования сессии TLS будет другим, авторы атаки приводят оценку приблизительно в 2 50 операций, что, впрочем, не является препятствием: на специализированном кластере среднего уровня — вычисления заняли менее суток). Кроме того, формат сообщений SSLv2 предписывает при подготовке сообщения к зашифрованию RSA использовать дополнение определённого формата, особенности обработки этого дополнения на серверной стороне позволяют построить криптографический оракул, делающий возможным расшифрование секрета из соответствующего TLS-соединения.

Атака проводится в несколько этапов. На первом этапе атакующий пассивно записывает TLS-трафик: предмет записи — начало TLS-сессий, использующее статический обмен RSA для передачи сеансового секрета. Именно TLS-сообщение, содержащее Premaster Secret, является целью атаки. Раскрыв информацию из данного сообщения, атакующий может вычислить сеансовые ключи и расшифровать весь записанный трафик сессии. На втором этапе — записанные сообщения с Premaster Secret преобразуются к виду, пригодному для отправки в качестве зашифрованного клиентского ключа в рамках SSLv2-сессии. На третьем этапе атакующий проводит попытки установления соединения с SSLv2-сервером, используя ответы сервера (требуется несколько десятков тысяч запросов) для расшифрования одного из подходящих Premaster Secret. Такое расшифрование состоит из набора шагов, в которых атакующий последовательно, на основе ответов сервера, модифицирует сообщение для следующего запроса.

Шифрование RSA — это всего лишь возведение открытого текста в степень со значением шифрующей экспоненты, выполненное по модулю ключа RSA (C = m e mod N — алгоритм описан выше). Дополнение, предписываемое используемым форматом, требует размещения в начале сообщения двух байтов со значениями 00 02. Если результат расшифрования не совпал с данным шаблоном, то сервер может выдать сообщение об ошибке, либо другим способом раскрыть информацию о неудаче. На этом наблюдении и основана исходная атака Блейхенбахера: известное значение двух первых байтов позволяет установить интервал, в котором лежит открытый текст (открытый текст — это число, полученное в результате возведения в степень mod N). Далее, умножая шифротекст на некоторое выбранное значение, воспользовавшись тем, что (C*K e ) = (m*K) e mod N, где m — открытый текст, и отправляя результат для расшифрования на сервер, атакующий может последовательно уменьшать интервал возможных значений шифротекста, с тем, чтобы в итоге получить единственное подходящее значение m. Использование в DROWN SSLv2 и экспортных ограничений, требующих короткого шифротекста (40 бит), позволяет существенно оптимизировать алгоритм Блейхенбахера, сократив число запросов к SSLv2-серверу до практически достижимых значений.

TLS и постквантовая криптография

Квантовый компьютер — это устройство, эффективно выполняющее алгоритмы квантовых вычислений. Термин «постквантовые», в контексте криптографии, обозначает стойкость к взлому с использованием квантовых алгоритмов на квантовом компьютере. Предполагается, что универсальный квантовый компьютер позволит реализовать алгоритмы, эффективное выполнение которых недоступно классическим компьютерам. Основные надежды связаны с алгоритмом Шора. Этот алгоритм, как уже рассказано выше, позволяет за обозримое время решать задачи, на сложности которых базируется стойкость и RSA, и ECDSA, и ECDH (и не только этих криптосистем). С прикладной точки зрения, появление квантовых компьютеров достаточной разрядности делает самые распространённые сейчас асимметричные криптосистемы нестойкими. Более того, можно будет расшифровать ранее записанный TLS-трафик, симметричные ключи для которого вычислялись только с использование упомянутых криптосистем (данная угроза не распространяется на экзотические реализации TLS с PSK, где в качестве одного из источников секрета используется общий симметричный ключ, известный сторонам заранее, при условии, что стороны обменялись этим ключом по защищённому от «квантового перехвата» каналу).

Что касается используемых сейчас в TLS симметричных шифров, то известные квантовые алгоритмы на их стойкость в целом влияют не критически: считается, что удастся получить лишь квадратичный прирост эффективности полного перебора, а это означает, что 256-битный ключ симметричного шифра сохранит 128 бит постквантовой стойкости. 128 бит вполне достаточно. Однако это рассуждение относится только к перебору. Полный перебор универсален и работает против схемы с любым симметричным шифром, кроме абсолютно стойких. Но это вовсе не означает, что не будут предложены квантовые алгоритмы, специально оптимизированные под конкретный шифр и существенно превосходящие перебор по эффективности. Тем не менее, так как универсального квантового алгоритма, быстро взламывающего базовые симметричные шифры TLS, не известно, то и проблем в части симметричных криптосистем в постквантовую эпоху для TLS (пока) не возникает. Главные проблемы относятся к асимметричным криптосистемам.

В TLS асимметричные криптосистемы используются на двух направлениях: аутентификация сторон соединения (электронная подпись, TLS-сертификаты) и получение общего симметричного секрета (варианты протокола Диффи-Хеллмана). Появление подходящих для практических атак квантовых компьютеров критически влияет на оба этих направления, однако практические механизмы влияния сильно отличаются. Так, взлом той или иной асимметричной криптосистемы электронной подписи позволяет атакующему подменять узлы и проводить активные атаки с перехватом сессий на начальном этапе, то есть, атаки посредника. А вот успешная атака в части симметричного секрета — позволит читать трафик сессий в пассивном режиме. Естественно, если рассматривать ситуацию с точки зрения массового использования, то пассивная атака оказывается гораздо более универсальной и, поэтому, опасной. Более того, как отмечено в разделе, посвящённом выбору параметров криптосистем, возможность успешно атаковать аутентификацию — бесполезна для ранее записанных сессий. Чего нельзя сказать про возможность расшифрования записанного трафика, защищённого симметричным шифром: здесь угроза квантовых алгоритмов гораздо выше и требует упреждающей реакции, поскольку необходимо обеспечить стойкость в течение некоторого времени (пока защищаемые данные не устареют). Поэтому первоочередные меры по защите TLS от «квантовых атак» направлены на внедрение постквантовых криптосистем для получения общего секрета. Если защитить симметричные ключи заранее, то появление квантового компьютера в будущем поставит под угрозу только достаточно старый трафик, который был записан до внедрения постквантовых криптосистем.

Стойкость (предполагаемая) к взлому на квантовом компьютере достигается благодаря тому, что постквантовые криптосистемы строят на математических конструкциях, не содержащих структур, для которых известны эффективные, в смысле атаки, квантовые реализации. Например, алгоритм Шора позволяет взломать RSA потому, что с помощью квантового компьютера возможно отыскать период достаточно простой функции (экспоненты). Знание периода позволяет быстро вычислить разложение модуля ключа на простые множители уже на классическом компьютере. Здесь эффективным квантовым воплощением базовой структуры как раз и является квантовая реализация упомянутой функции, благодаря которой всё пространство значений можно уложить в квантовые регистры и провести квантовое вычисление, определяющее период (на классическом компьютере — пришлось бы проверять значения функции для отдельных элементов, что потребовало бы слишком много операций). Если же подходящих структур и методов преобразования не известно, то алгоритм считается стойким ко взлому на квантовом компьютере. Обратите внимание, что речи о доказанном отсутствии квантовых алгоритмов взлома пока что не идёт (доказывать отсутствие алгоритмов вообще непросто).

На настоящий момент (октябрь 2023) постквантовые криптосистемы в TLS пока используются только в экспериментальном статусе. Предложено много разных вариантов таких криптосистем, но ни один из них пока не находится в стадии полной готовности, подходящей для повсеместного внедрения в TLS. Так, NIST проводит собственный процесс выбора постквантовых криптосистем. В 2022 году этот процесс позволил выбрать ряд алгоритмов для будущей стандартизации, однако работа пока продолжается.

На начальном этапе постквантовая криптосистема будет внедрена в TLS в дополнение к классическим. То есть часть общего симметричного секрета будет генерироваться по постквантовому алгоритму, при этом эффективная разрядность полного секрета возрастёт, но классическая часть всё ещё будет обеспечивать необходимый минимум. Это требуется для того, чтобы не потерять уже имеющуюся стойкость, если постквантовый алгоритм окажется ненадёжным — дело в том, что даже стойкость ко взлому на квантовом компьютере не гарантирует, что для конкретного алгоритма нет эффективных классических атак. Другими словами: классический протокол, например, ECDH, используется для генерирования общего секрета разрядностью в 256 бит, а постквантовый алгоритм — позволяет согласовать ещё 256 бит. Если использование квантового компьютера приводит к раскрытию ключа ECDH, то остаётся ещё 256 бит «постквантового секрета», если же постквантовая система оказалась уязвима для классической атаки, а квантового компьютера ещё нет, то остаётся 256 бит ECDH. Понятно, что в наихудшем варианте, — когда и квантовый компьютер раскрывает секрет ECDH, и постквантовая криптосистема оказалась уязвимой, — сессия будет взломана полностью, но такой вариант менее вероятен, чем ошибки в реализации новых, постквантовых, алгоритмов.

По только что описанной схеме один из криптографических протоколов с постквантовой стойкостью был добавлен в браузер Chrome в августе 2023 года, как эксперимент, а именно — добавлена гибридная схема передачи (инкапсуляции) секретного ключа X25519Kyber768, способ использования которой ниже кратко рассмотрен. X25519Kyber768 в Chrome используется в соединениях TLS 1.3, а архитектура протокола позволяет так вписать Kyber768 в общий алгоритм, что никаких других элементов затронуто не будет: то есть, в логике сообщений ничего не меняется, весь процесс установления TLS-соединения остаётся таким же, как и без Kyber768; новая криптосистема влияет только на некоторые детали шагов получения общего симметричного секрета.

Kyber768 в браузере Chrome (Chromium). Постквантовая гибридная схема использует криптосистему X25519 в качестве классической и Kyber768 — в качестве постквантовой. X25519, которая несколько раз упоминается выше, это хорошо известный вариант протокола Диффи-Хеллмана на эллиптической кривой, при этом в криптосистеме сразу зафиксирована кривая (Curve25519) и ряд сопутствующих параметров, а открытые значения DH передаются в «упакованном» виде (открытый ключ здесь — точка на кривой, см. «Приложение А»).

Kyber768 (вариант Kyber) — это асимметричная криптосистема, позволяющая реализовать зашифрование и расшифрование. В данном случае схема используется в режиме KEM (Key Encapsulation Mechanism — дословно: механизм инкапсуляции ключа), верхнеуровневая логика при этом совпадает с RSA-шифрованием. Криптосистема Kyber, — а точнее CRYSTALS-KYBER, — первой рекомендована NIST к стандартизации в ходе процесса выбора постквантовых криптосистем. Это, впрочем, всё ещё предварительные результаты: какого-то опыта, — как с квантовыми компьютерами, так и с постквантовыми криптосистемами, — пока не накоплено.

Объединённая криптосистема называется X25519Kyber768, однако, так как спецификации пока находятся в статусе черновика (2023), а криптосистема Kyber может поменяться не только в деталях, но и существенным образом, полное название такое: X25519Kyber768draft00. Этому обозначению уже соответствует индекс 0x6399 в реестре IANA.

Криптосистема Kyber768 основана на задаче восстановления исходного набора значений (вектора) по набору, элементы которого переданы с «ошибками» (заданными отклонениями), то есть, концепция, в самом общем виде, происходит из теории помехоустойчивого кодирования (коды с коррекцией ошибок). Базовая задача называется Module-LWE — то есть, «LWE для модулей», где LWE — Learning With Errors, задача восстановления значений по векторам «ошибок». Данный класс криптосистем в формулировках сложнее и чем RSA, и чем ECDSA. Однако, чтобы составить общее представление о приницпе использования Kyber для обмена ключами в TLS, подробное знакомство с математическими основами не требуется.

Для прикладного воплощения теоретической идеи Kyber использует кольца многочленов — несколько упрощённо можно сказать, что операции сводятся к умножению и сложению многочленов особого вида. При этом из многочленов строятся матрицы и векторы (откуда, собственно, и «модули» в названии базовой задачи). Такой математический аппарат и должен обеспечить стойкость к атакам на гипотетическом квантовом компьютере, поскольку эффективных квантовых алгоритмов взлома на этом направлении пока не найдено. Естественно, предполагается, что схема обладает и классической стойкостью.

Итак, в TLS логика использования KEM Kyber совпадает с описанным выше RSA-шифрованием для передачи сеансового секрета, однако стороны меняются местами и открытый ключ здесь присылает клиент. А именно: TLS-клиент передаёт в составе ClientHello (в расширении key_share, см. уточнение ниже) свой открытый ключ Kyber768, сервер генерирует общий секрет, зашифровывает его Kyber, используя клиентский открытый ключ, и отправляет клиенту в составе ответного ServerHello (серверное key_share); клиент, которому известен соответствующий секретный ключ, расшифровывает полученный общий секрет. Для получения симметричного секрета используется заданная функция генерирования ключа (KDF), входящая в состав криптосистемы. Эта схема и называется KEM — симметричный ключ здесь как бы скрывается внутри (инкапсулируется) защищённого при помощи асимметричной криптосистемы сообщения (KEM — это просто обобщение для многих способов перадачи ключа). Обратите внимание, что сервер получает симметричный сеансовый секрет TLS сразу, вместе с зашифрованным Kyber768 сообщением.

Так как криптосистема гибридная, то в соответствующем блоке key_share, с идентификатром 0x6399, передаются в виде одного массива два ключа: 32 байта открытой части DH X25519 (открытый ключ X25519) и 1184 байта ключа Kyber768. Значения объединяются простой конкатенацией: к байтам ключа X25519 присоединяются (справа) байты ключа Kyber768. Открытый ключ Kyber768 — это набор из трёх многочленов, где каждый многочлен представлен кортежем своих коэффициентов, а именно — 256 коэффициентов, которые превращаются в 384 байта записи для каждого многочлена; кроме того, в состав ключа входит дополнительный 256-битный параметр — ещё 32 байта (384*3+32 == 1184). Открытый ключ Kyber768 существенно отличается по представлению, например, от RSA, однако очень близок по количеству байтов к длинным RSA-ключам.

На сервере данные разделяются (по длине записи) и используются для обеих криптосистем. А именно: для X25519 сервер вычисляет общий секрет DH и серверную открытую часть DH (B), точно так же, как это делалось бы в случае отдельной криптосистемы X25519; для Kyber768 – сервер генерирует общий секрет и оборачивает его в KEM (то есть, зашифровывает исходное секретное значение, используя открытый ключ Kyber, присланный клиентом – тем самые 1184 байта). Два секрета сервер объединяет в один массив простой конкатенацией. Есть важная особенность: для X25519 общий секрет — это результат умножения открытой части DH клиента (A) на секретный скаляр сервера d: s = d*A; а для Kyber – сервер выбирает исходное значение, которое отправляет клиенту в зашифрованном виде. При этом внутри KEM Kyber для вычисления секрета по исходному значению используется отдельная функция (KDF), подмешивающая ещё и значение открытого ключа, это необходимый шаг, но, с точки зрения именно логики получения секрета, он не так важен. Секрет, генерируемый в рамках Kyber768 в TLS – это тоже 32 байта (256 бит). После завершения певого этапа формирования секрета X25519Kyber768 сервер получает общий симметричный секрет, представляющий собой объединение выдачи двух алгоритмов: 32 байта и ещё 32 байта. Кроме того, сервер получил открытую часть DH и зашифрованный симметричный секрет (это только часть, предназначенная для Kyber, результат X25519 сюда не попадает).

Серверное расширение key_share формируется похожим на клиентскую часть образом: к 32 байтам открытой серверной части X25519 присоединяются байты шифротекста с симметричным секретом, который зашифрован Kyber (длина шифротекста — 1088 байтов, всего 1120 байтов). Ответное key_share сервер отправляет клиенту в открытой части сообщений TLS, в ServerHello, после чего генерирует на основе общего секрета набор симметричных сессионных ключей и переходит к зашифрованному обмену данными.

Клиент, получив key_share X25519Kyber768, разделяет данные на открытую часть обмена DH X25519 (B) и шифротекст Kyber768. По значению B клиент вычисляет общий секрет X25519 (32 байта), который совпадает с серверным. Используя секретный ключ Kyber768, клиент расшифровывает шифротекст и вычисляет секрет Kyber, который передал сервер. Оба полученных значения объединяются, результат должен совпасть с серверным. В Kyber есть вероятностный элемент: так как это схема, концептуально происходящая из кодов с коррекцией ошибок, имеется очень малая вероятность, что “ошибка” всё же останется, а клиент и сервер получат разные значения секрета. На основе объединённого секрета клиент вычисляет набор симметричных ключей, после чего может проверить подлинность и расшифровать следующие сообщения сервера.

Метаинформация о соединении

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

Рассмотрим TLS-сеанс между браузером и веб-сервером, соответствующий штатной (без использования дополнительных средств защиты информации) работе пользователя с некоторым веб-интерфейсом. Например, заполнение веб-формы на сайте. Версия протокола — до TLS 1.3. Уже в момент установления соединения, третья сторона, прослушивающая канал, получает информацию о следующих параметрах соединения:

1) Время установления соединения и его продолжительность. Это очевидные параметры, они определяются из состава переданных TLS-сообщений и общих характеристик трафика. Скрыть данную метаинформацию возможно, однако TLS тут никаких инструментов сокрытия не предлагает: протокол проектировался в модели, которая прямо допускает, что прослушивающая сторона может непосредственно видеть пакеты, формирующие весь трафик TLS-сессии. Это, конечно, обусловлено основным предназначением протокола. Дело в том, что вычислительные затраты на сокрытие факта соединения весьма и весьма значительны, а TLS — это протокол для массовых, быстрых интернет-сервисов, которые не готовы тратить ресурсы на качественную стеганографию. Тем не менее, давление современной «информационной реальности» таково, что для TLS разрабатывают решения, позволяющие, фактически, скрыть сведения о факте полезного соединения, обернув одно TLS-соединение в другое. Ключевым на этом направлении сейчас является технология ECH, которая описана выше.

2) IP-адрес сервера и IP-адрес клиента. Известны из TCP-соединения, не зависят от TLS напрямую, однако протокол неявно подразумевает, что адреса клиента и сервера TCP-соединения — совпадают с адресами клиента и сервера на уровне TLS; в частности, типовая реализация протокола не предполагает проксирования TLS-данных (однако такое проксирование, опять же, может быть реализовано дополнительными средствами — см. предыдущий пункт). В целом ряде практических случаев утечка сведений об IP-адресе сервера не даёт никакой ценной информации: один и тот же адрес может соответствовать десяткам тысяч различных ресурсов, выбор которых производится по имени. При этом подобное «перемешивание» IP-адресов и имён является эффективным инструментом сокрытия того сервиса, с которым в действительности работает клиентское приложение: при должном подходе IP-адрес вообще может нести лишь информацию о провайдере соединения, но не о сервисе.

3) Сведения о том, устанавливал ли браузер соединение с данным TLS-сервером ранее. В TLS предусмотрены механизмы ускоренного установления соединения, а они подразумевают передачу дополнительных «тикетов» в сторону сервера, эти тикеты передаются в открытом виде. Кроме того, отличается сам алгоритм повторного (ускоренного) соединения, что позволяет узнавать такие сессии. При этом, конечно, ничто не мешает клиенту не использовать ускоренные схемы.

4) Имя сервера. Символьное имя сервера (вида example.com) передаётся браузером в открытом виде на этапе установления соединения. Речь про поле SNI, которое описано выше. Методы защиты от утечки данного имени только разрабатываются, поэтому, в случае с вебом (HTTPS), можно считать, что имя сервера сейчас передаётся повсеместно.

5) Дополнительные имена, связанные с данным сервером. На этапе установления соединения, подразумевающего аутентификацию сервера (подавляющее большинство соединений HTTPS), сервер передаёт TLS-сертификат в открытом виде (за исключением TLS 1.3). Сертификат содержит поля с указанием различных имён, для которых данный сертификат валиден. Кроме того, открытый ключ из сертификата позволяет идентифицировать сервер.

6) Выбранные криптографические параметры TLS-соединения. Шифр, алгоритм электронной подписи и алгоритм вычисления кода аутентификации — передаются в открытом виде.

7) Примерный объём переданных данных, примерные действия, выполненные пользователем. Прослушивающая сторона может определить длину передаваемых TLS-записей, штатная работа протокола (до версии 1.3) не подразумевает каких-то эффективных средств маскировки длины сообщений, если они содержат достаточное количество байтов (маскировать длину данных необходимо дополнительно). Например, если пользователь загружал через веб-форму файл существенного объёма, то количество переданных байтов, очевидно, будет отличаться от сценария, когда пользователь просто закрыл веб-форму. Анализ длины переданных записей, порядка их следования, и сопоставление результата с особенностями веб-интерфейса, нередко позволяет точно определить, какие именно действия совершил пользователь.

Метаинформация приобретает особое значение в тех случаях, когда третья сторона может накапливать сведения о большом количестве TLS-соединений. Это относится как к ситуации, когда записывается трафик множества соединений одного и того же клиента (с разворачиванием по времени), так и к ситуации, когда ведётся одновременная запись сессий многих клиентов (разворачивание по клиентам).

Атаки со стороны сервисов

Для большого класса добротных, стойких криптосистем, широко используемых сейчас в TLS на практике, возможно восстановление сеансового ключа из записанного трафика, при условии, что атакующая сторона имеет в своём распоряжении секретный серверный ключ (ключ из пары, открытая часть которой указывается в сертификате сервера). Это означает, что получив секретный ключ сервера (не сеансовый!), кто-то может расшифровать накопленные ранее записи TLS-сеансов между клиентом и сервером. Упомянутый ключ может быть раскрыт разными способами: например, его можно скопировать с сервера, если есть доступ, или он может просто оказаться нестойким (такое случается не так редко, как можно подумать). Сгенерированный по протоколу Диффи-Хеллмана сеансовый ключ также может стать известен злоумышленнику: либо в результате активной атаки на уровне канала (как Logjam), либо в результате получения доступа к серверу, где сеансовый ключ может сохраняться достаточно долго, и не обязательно в защищённом хранилище. Очевидно, что если атакующая сторона получила соответствующий сеансовый ключ, то она может раскрыть TLS-трафик. Секретный серверный ключ или TLS-сертификат для этого не требуются.

Возможность выпустить TLS-сертификат для атакуемого домена сама по себе никак не помогает расшифровать TLS-трафик, идущий в этот домен, даже если трафик записывается. Процедура выпуска сертификата не требует передачи секретного ключа в удостоверяющий центр (передаётся только открытый ключ), поэтому у удостоверяющего центра секретного серверного ключа тоже нет, за исключением распространённого сейчас случая, когда заказчик поручает генерацию такого ключа УЦ (что, впрочем, является административной, а не технической, проблемой).

Однако валидный TLS-сертификат, выпущенный для атакуемого домена, позволяет провести незаметную для пользователя атаку типа «человек посередине». Для этого требуется, чтобы между атакуемым пользователем и сервером существовал управляемый атакующим узел, активно перехватывающий трафик. Этот узел выдаёт себя пользователю за легитимный сервер, предъявляя тот самый валидный сертификат. Пассивное прослушивание канала не позволяет раскрыть TLS-трафик подобным образом – наличие сертификата или секретных ключей УЦ никак тут не помогает.

Перехват TLS-соединения может быть автоматизирован – существуют специальные узлы-прокси (SSL-прокси), которые выполняют такой перехват на лету, в том числе, генерируя нужные сертификаты. В такой прокси должен быть загружен сертификат и секретный ключ, позволяющие подписывать другие сертификаты (например, годится промежуточный сертификат УЦ, выпущенный для этих целей и соответствующий ему секретный ключ). Такой «человек посередине» не работает при наличии некоторых дополнительных мер: например, установление TLS-соединения требует взаимной аутентификации, и перехватывающему узлу недоступен клиентский секретный ключ (либо ключи УЦ, удостоверяющего клиентский ключ); или – пользовательский браузер ведёт реестр отпечатков открытых ключей сервера, которым он доверяет; или – пользователь применяет дополнительные источники сведений о разрешённых ключах и сертификатах, которые недоступны для подмены на перехватывающем узле (таким источником может служить DNS, либо другая база данных).

На практике, для массовых сервисов, возникают другие технические направления атак, напрямую не связанные с какими-то особенностями TLS.

Так, массовые онлайн-сервисы используют TLS/SSL termination: то есть, пользовательский TLS-трафик в зашифрованном виде доходит только до пограничного прокси, где благополучно транслируется в открытый протокол, обычно это HTTP, сответствующий HTTPS, который дальше ходит по внутренним (в логическом, а не техническом смысле) сетям сервиса в открытом виде. Тотальный HTTPS, с ростом числа клиентов, быстро превращается в неподъёмную, плохо масштабируемую технологию, поэтому TLS/SSL termination является весьма распространённым решением. Если система инспекции трафика (DPI) находится внутри сетей сервиса, за таким пограничным прокси, то никакой TLS ей не помешает. Именно так получают доступ к данным платёжных систем и веб-почты специальные службы, располагающие, на законных основаниях, собственным оборудованием DPI за пограничными прокси.

Сеансовые ключи могут экспортироваться сервером наружу, в другие системы, которые, например, осуществляют балансировку нагрузки или «очистку» трафика. В некоторых случаях вообще используются услуги третьей стороны для организации TLS-соединения. Кроме того, внутренний трафик распределённых сервисов с лёгкостью ходит между узлами и дата-центрами по арендованным у крупных операторов каналам связи в открытом виде, такой трафик может прослушиваться, хотя для пользователя он выглядит как TLS-соединение.

Иными словами: TLS не предоставляет абсолютной защиты, но в подавляющем большинстве сценариев использования Интернета этот протокол делает обмен информацией хорошо защищённым; для повышения скрытности и безопасности, если такое требуется, TLS должен использоваться совместно с другими решениями.

Приложение А. Конечные поля и эллиптические кривые в криптографии

В этом приложении в довольно вольном формате рассмотрены элементарные математические основы, на которых строятся эллиптические криптосистемы, упоминающиеся в основном тексте.

Для начала потребуется базовый инструментарий, прежде всего — конечное множество c дополнительной структурой, которая определяется парой операций над элементами множества, обладающих свойствами «обычных» сложения и умножения. Мы собираемся решать в этом множестве некоторые уравнения, поэтому важно, чтобы результат применения операций не выходил за пределы данного множества. Не вдаваясь в алгебраические детали, достаточно вспомнить про деление с остатком — оно как раз позволяет построить нужную структуру. Для примера, будем делить на 17: всякое натуральное число можно отождествить с остатком от его деления на 17. У нас получится множество из семнадцати элементов, соответствующих числам от 0 до 16. Можно сказать, что здесь сохранились привычные операции сложения и умножения. Это легко проверяется: 11 + 13 = 7, где 7 — остаток, получившийся при делении 24 на 17; 6*9 = 3, так как 54 = 3*17 + 3. В нашей структуре можно вычитать и делить, то есть, по-научному, она образует поле, однако и вычитание, и деление — несколько отличаются от «обычных»; эти детали мы сейчас не станем рассматривать, но полем всё же получившийся объект называть будем. Точнее — конечным полем, потому что в нём конечное число элементов.

Описанный только что пример вовсе не является каким-то чрезмерным упрощением: конкретные реализации ECDSA именно с такими полями («остатками от деления») и работают, но в качестве основы берётся не 17 или 19, а очень большое простое число (это число, задающее поле, называют модулем; чтобы «по остаткам» получилось именно поле, модуль обязательно должен быть простым числом; в криптографии используются и другие поля, практические воплощения которых строятся «на многочленах», здесь самое заметное отличие будет в количестве элементов; мы, опять же, пропускаем эти детали, иначе можно уйти далеко в сторону).

Для нашей задачи принципиально важен только один момент: можно простым способом, позволяющим проводить эффективные вычисления, построить конечное множество, на котором действуют привычные операции сложения и умножения. Конечность здесь имеет прикладное значение — мы собираемся «считать на компьютере» и нам потребуется эффективный алгоритм, позволяющий за конечное число шагов построить любой элемент нашего множества из других его элементов. Вот теперь можно переходить к кривым.

Рассмотрим формулу 2x + 3 = y. Можно ли найти в нашем множестве остатков от деления на 17, с введённой структурой сложения и умножения, пары элементов (x,y), удовлетворяющие этой формуле? Да, это легко сделать: 1 и 5, 3 и 9, 10 и 6. Формулу можно выбрать посложнее. Эллиптической кривой соответствует y 2 = x 3 + ax + b, где a, b — коэффициенты, которые определяют конкретный экземпляр кривой; a и b — элементы выбранного поля, на которые накладываются дополнительные ограничения, которые мы пропустим. В формуле используется возведение в степень. Под этой операцией понимается последовательное умножение элемента на себя, то есть ничего нового здесь не написано, это всё привычные операции, но результат берётся по модулю некоторого (простого) числа.

Теперь, взяв подходящую (см. выше: y 2 = x 3 + ax + b) формулу, мы можем выбрать в нашем множестве со структурой пары элементов, соответствующие формуле. Множество таких пар и будет в нашем случае эллиптической кривой, каким бы странным это не казалось. Да, это не совсем кривая в «бытовом» понимании, но это не важно: в контексте рассматриваемой криптосистемы важны именно пары значений, задаваемые уравнением кривой (мы называем его просто формулой). Обычно, таких пар в правильно выбранном поле более чем достаточно. Пары элементов (x,y) называют точками эллиптической кривой над конечным полем. Это терминологическое соглашение. Конечно, за соглашением кроется глубоко теоретическая математика, но она, тем не менее, напрямую в прикладной криптографии не используется, в том смысле, что вовсе не обязательно представлять себе эллиптическую кривую над конечным полем как некую «линию» (но можно попробовать и сделать шаг на территорию геометрии над конечными полями; вообще, с точки зрения чистой математики, эллиптическая кривая объект гораздо более общий, чем обозначено в нашем изложении, да и строится он другими способами).

Пусть у нас есть ещё пара формул, которые позволяют по кортежу значений, состоящему из двух пар (x,y) и (u,v), вычислить другую пару (k,l). Важное свойство: новая пара (k,l) тоже удовлетворяет уравнению кривой. То есть, мы берём две точки, вспоминаем, что каждая из них — это пара элементов поля, связанных между собой уравнением кривой, и применяем к этим элементам формулу, которая сопоставляет двум элементам — третий. Обозначим пары элементов буквами �� и ��, (x,y)=��, (u,v)=��. Примем, что упомянутые формулы — это функции F1(��,��) и F2(��,��) от пар элементов нашего множества (поля). Тогда, если у нас на входе две точки (x,y)=�� и (u,v)=��, то, применив функции, мы получаем третью точку (F1(��,��), F2(��,��)), то есть (k,l), где k,l есть значения, элементы поля, вычисляемые по некоторым формулам. Ключевое свойство этих формул в том, что получившаяся пара элементов (k,l) удовлетворяет нашему уравнению кривой.

Только что описанные формулы переводят точки кривой в точки кривой, то есть задают некоторую операцию на множестве этих точек (или, эквивалентно, на _выбранных_ парах элементов нашего поля). Обозначим эту операцию символом «∘». Внутри нашего множества со структурой появилось подмножество пар элементов, соответствующих точкам кривой. Операция ��∘�� = �� задаёт (k,l) — третью пару элементов, или третью точку, соответствующую двум другим. Формулы, преобразующие элементы, должны быть устроены таким образом, чтобы соответствующая им операция обладала определёнными свойствами. Например, она коммутативна и ассоциативна; более того, множество пар с данной операцией образует группу, то есть операция однозначна, существует «нулевая» точка, которая описана ниже, и обратные элементы (если подходить совсем строго, то для получения обратного элемента нужна вторая операция, но она у нас тоже есть). Именно поэтому говорят о группе точек эллиптической кривой. Применение операции к парам элементов, соответствующих точкам кривой, не выводит нас за пределы подмножества пар, которые мы назвали точками. Данную операцию принято называть сложением точек, но это, опять же, всего лишь удобное терминологическое соглашение.

Итак, мы использовали пары элементов поля для построения группы точек эллиптической кривой над конечным полем. То есть, в основе этой группы — два экземпляра поля (потому что у нас пары значений).

Операцию сложения точек можно применять к одной и той же точке. (Строго говоря, сами формулы, задающие сложение, при этом могут быть разными, то есть, различаются формулы для двух различных точек и формулы для сложения одной точки с самой собой, для удвоения точки. Впрочем, можно так подобрать структуры, что формулы окажутся одинаковыми, но это технические детали.) Итак, можно складывать точку саму с собой. Вспомним, что наше исходное множество — конечное. Поэтому множество пар элементов, соответствующих структуре точек эллиптической кривой, тоже конечно. Это означает, что на каком-то шаге последовательное сложение точки с самой собой даст в результате эту же точку (мы как бы вернёмся в начало; можно было бы предположить, что «зацикливание» произойдёт на какой-то другой точке, а не на начальной, но это не так, ввиду свойств операции сложения точек).

Данное наблюдение непосредственно связано с особой «нулевой» точкой ��, главное свойство которой совпадает со свойствами привычного нуля по сложению — сумма любой точки �� с «нулевой» даёт эту же точку ��: ��∘�� = ��∘�� = ��. Возникает вопрос о координатах, то есть, о паре элементов поля, которые соответствуют точке ��. Чтобы не усложнять изложение, примем, что «нулевой» точке соответствует пустая пара элементов нашего множества. Точки, которые в сумме дают точку �� — называют обратными (аналогом этого, например, для целых чисел по сложению, является число A и его «минус», то есть -A, так как A + (-A) = 0). Если говорить о парах элементов в практических применениях, то для взаимно обратных точек, сумма которых даст ��, один элемент будет одинаковым, а два других — обратными. Например: (x, y) и (x, -y). Если последовательно складывать какую-либо точку с собой, то в какой-то момент обязательно получим точку ��.

Только что описанная структура является чисто алгебраическим воплощением метода секущих и касательных, которым обычно геометрически иллюстрируют механизм сложения точек на эллиптической кривой, в её вещественной интерпретации: секущая проходит через две точки, которые суммируются, а касательная — используется при удвоении точки. Очень известная картинка. При этом на иллюстрациях рисуют кривую, обладающую нужной непрерывностью. Уравнения секущих и касательных служат основой для построения формул сложения точек. Элементы, входящие в пары, называют координатами.

Вернёмся к сложению точки с ней самой. ��∘�� можно переписать как 2��, отразив тем самым, что мы сложили две «копии» точки. Тогда 5�� = ��∘��∘��∘��∘��, и так далее. Запись очень похожа на умножение, но это не умножение точек («умножения» для точек у нас вообще нет — мы его не определили), поэтому говорят об умножении точки на скаляр. Скаляром здесь называют целое число, соответствующее количеству «копий» точки. Умножение на скаляр (n��) имеет свои свойства. Например, в записи 5�� можно представить число 5 в виде суммы 3+2, получим (3+2)�� — такая запись соответствует тому, что в «разложение» суммы точек как бы добавили скобки, вот так: (��∘��∘��)∘(��∘��), или 3��∘2�� . Здесь необходимо понимать, что используются два различных «сложения»: сложение в целых числах «+», и сложение точек кривой («∘»). (В алгебре такая структура называется модулем, да, тоже модулем — см. первый абзац, — и встречается сплошь и рядом, в том числе, и под другими названиями.)

По свойствам, умножение на скаляр совпадает с возведением в степень, операции отличаются только способом записи. Именно поэтому в описаниях эллиптических криптосистем фигурируют «логарифмы» — так сложилось исторически. Возможность переписать ��∘��∘��∘�� как 2��∘2��, то есть, как удвоение точки 2�� — даёт необходимый механизм, позволяющий быстрее умножать точки на скаляр, если известно значение скаляра. Только благодаря этому и работают на практике криптосистемы, основанные на дискретном логарифмировании в группе точек эллиптической кривой. Это весьма общее свойство, которое необходимо для построения многих других практически полезных криптосистем. Только что описанное умножение точки на скаляр — прямо используется в протоколе Диффи-Хеллмана на эллиптических кривых (см. основной текст). Стойкость протокола основана на том, что вычислительно сложной является обратная задача: по известным точкам �� = n��, найти n.

Приложение Б. Применение TLS для защиты других протоколов

Среди самых распространённых в Интернете сценариев использования TLS находится HTTPS — защищённая версия протокола HTTP, которая повсеместно применяется для работы с веб-сайтами, а с некоторых пор и в целом ряде других случаев. Например, в 2018 году статус RFC 8484 получил протокол DNS-over-HTTPS (DoH), который, в полном соответствии с названием, позволяет отправлять запросы и получать ответы DNS через HTTPS. DNS — система доменных имён — это фундаментальная часть Интернета, представляющая собой распределённую базу данных, которая хранит пары «ключ-значение» и предоставляет механизм извлечения этих записей. Самый простой случай использования DNS — это поиск IP-адреса, соответствующего доменному имени: ключом здесь является доменное имя (например, example.com), а значением — IP-адрес (например, 192.168.0.3). Мы не рассматриваем подробности устройства DNS в этом тексте, а остановимся только на способах применения TLS для защиты информации, передаваемой при работе с доменной системой имён.

Извлечение информации из DNS инициирует DNS-клиент. Например, это может быть служба доменных имён операционной системы (либо встроенный в прикладные библиотеки сервис). Обычно, системная служба является самой простой из возможных: получив запрос от приложения, эта служба либо отвечает данными из локальных таблиц, либо просто переправляет запрос внешнему сервису поиска (который называется «рекурсивным резолвером») и ожидает ответ от него; основная особенность здесь в том, что рекурсивный опрос служба самостоятельно не выполняет. Внешний рекурсивный резолвер, осуществляющий поиск в DNS, традиционно предоставляется провайдером интернет-доступа. Кроме того, распространение получили глобальные общедоступные DNS-сервисы, например 8.8.8.8 (Google) и 1.1.1.1 (Cloudflare).

В классическом варианте DNS — вся информация передаётся в открытом виде. Именно обмен информацией между DNS-клиентом и внешним рекурсивным резолвером защищается при помощи DNS-over-HTTPS. Эта технология предполагает, что запросы к DNS-серверу направляются по HTTPS, фактически аналогично тому, как это происходит в случае веб-узлов. Так как HTTPS использует TLS для защиты информации, запросы и ответы оказываются скрыты от прослушивания третьей стороной.

Применение TLS для защиты DNS позволяет, во-первых, провести аутентификацию DNS-сервера, во-вторых, защитить адресную информацию от подмены. Аутентификация может быть выполнена штатным для TLS способом, при помощи TLS-сертификатов. Защита от подмены является основным свойством протокола TLS. Таким образом, TLS переводит использование DNS на новый уровень, решая ряд проблем безопасности. Например, в DNS не предусмотрено никаких механизмов, позволяющих убедиться, что на запросы по некоторому IP-адресу отвечает именно тот DNS-сервер, который предполагается (ни IP, ни UDP, ни TCP не предполагают механизмов проверки подлинности узлов). Закрытие содержания DNS-трафика от прослушивания при помощи шифра позволяет перекрыть канал утечки сведений о веб-узлах и других интернет-ресурсах, используемых клиентом. Не менее важной оказывается и защита от подмены: дело в том, что обычные DNS-запросы и DNS-ответы могут быть перехвачены транзитными узлами, а передаваемая в них информация — может быть изменена, например заменён IP-адрес, при сохранении прочих свойств пакета. Подобное изменение информации приведёт к тому, что соединение будет установлено не с тем узлом, которому в действительности соответствует DNS-имя.

Очевидно, что для DoH требуется поддержка на стороне DNS-сервера. Такая поддержка уже доступна во многих приложениях. На стороне клиента DNS-over-HTTPS уже поддерживается браузерами Mozilla Firefox, Chrome, Microsoft Edge и др. Случай с браузерами является показательным: обычно, прикладные программы используют для работы с DNS системные средства или специальные стандартные библиотеки, однако для DoH работа с DNS осуществляется встроенными инструментами самого браузера.

DoH если и выглядит разумной технологией, то только для защиты канала между прикладной программой и внешним сервисом DNS-резолвера. При этом сама доменная система имён содержит и не менее важное второе плечо: это обмен информацией между резолвером и серверами DNS, осуществляющими поддержку доменных зон разного уровня (рекурсивный поиск). Существует другой вариант протокола, защищающего DNS при помощи TLS: он так и называется — DNS-over-TLS (RFC 7858, DoT). Этот вариант отличается от DoH тем, что здесь TLS используется «напрямую», то есть без дополнительной внутренней обёртки в виде HTTP. DoT предлагает все те же возможности защиты, что и DNS-over-HTTPS, но не требует реализации обработки HTTP-запросов и ответов: DNS-трафик непосредственно передаётся внутри защищённых TLS-записей, позволяя, фактически, надстроить над обычным DNS-сервером TLS-прокси. По этой причине DoT гораздо лучше подходит для обмена информацией между DNS-серверами при рекурсивном поиске. Понятно, что DoT может быть эффективно использован вместо DoH и для защиты запросов между прикладным DNS-клиентом и DNS-резолвером.

(Отдельно нужно отметить, что в DNS давно существует механизм криптографической защиты адресной информации — DNSSEC. Этот механизм позволяет удостоверить подлинность информации, полученной из DNS, при помощи электронной подписи. При этом DNSSEC не подразумевает аутентификации узлов, участвующих в обмене данными, но в соответствующей модели угроз этого и не требуется: если подпись на данных валидна, то не имеет значения, каким способом эти данные получены — из доверенного и аутентифицированного источника или нет. Поэтому использование TLS в DNS не отменяет DNSSEC, а лишь служит дополнением, защищающим каналы передачи данных.)

Приложение В. TLS и криптосистемы ГОСТ (ГОСТ-TLS)

Современный перечень российских криптосистем, определённых в серии ГОСТ 34.10, 34.11, 34.12, включает два шифра, хеш-функцию и электронную подпись. Этих элементов достаточно для того, чтобы построить вариант протокола TLS, использующий только российскую криптографию. Такие протоколы описаны и используются. Их принято называть ГОСТ-TLS. Помимо внутренних российских спецификаций, практически все элементы описаны в соответствующих RFC, например: RFC 9189, RFC 9058, RFC 7801, RFC 8891, RFC 7091, GOST with TLS 1.3 (draft) и др. Наиболее актуальная версия — TLS 1.3. ГОСТ-вариант этой спецификации поддерживает все особенности TLS 1.3 (уточнение 13/11/22: кроме сокращённых вариантов Handshake с данными 0-RTT, которые прямо запрещены спецификацией ГОСТ) и аналогичен ему по архитектуре.

Сравним основные криптографические подсистемы «обычного» TLS и ГОСТ-TLS.

  1. Хеш-функция. Пример для TLS: SHA-256. В ГОСТ-TLS используется сходная по свойствам и параметрам хеш-функция «Стрибог» из современной ГОСТ-серии 34.11.
  2. Электронная подпись. Пример для TLS: ECDSA. В ГОСТ-TLS — алгоритм из ГОСТ-серии 34.10. ГОСТ-подпись (современной версии) работает на том же математическом аппарате, что и ECDSA, то есть, тоже использует группу точек эллиптической кривой.
  3. Шифр. Пример для TLS: AES. В ГОСТ-TLS используется либо шифр «Магма», ставший уже классическим, поскольку ведёт свою историю из 70-х годов прошлого века, либо более современный «Кузнечик», который схож с AES по основным принципам построения. Оба шифра определены в ГОСТ-серии 34.12.
  4. Режим шифрования. Пример для TLS: GCM. В ГОСТ-TLS используется AEAD-режим MGM.
  5. Обмен симметричными ключами. Пример для TLS: ECDH. В ГОСТ-TLS (1.3) используется тоже ECDH, но с собственными параметрами и алгоритмами получения ключей из секрета.

Для ГОСТ-TLS выпускаются TLS-сертификаты, использующие ГОСТ-подпись. Эти сертификаты соответствуют по формату сертификатам TLS, описанным выше. Отличия касаются представления ключей и идентификаторов алгоритмов.

Автор выражает признательность Дмитрию Белявскому и читателю блога dxdt.ru Z.T. за ценные замечания и уточнения, Николаю Шаплову — за полезные комментарии по структуре текста.

Это версия 1.8 описания TLS от 06/10/2023; документ будет дополняться. Предыдущая версия (1.7) была опубликована 13/11/2022. Комментарии, уточнения, пожелания и вопросы — лучше всего направлять электронной почтой, адрес указан на сайте автора: dxdt.ru.

Методы обнаружения ошибок

Для обнаружения ошибок применяются методы (техники кодирования), основанные па определении вероятности получения приемником достоверной кодовой комбинации. В качестве такой комбинации может выступать любая протокольная единица данных (PDU, Protocol Data Unit) — блок битов, передаваемый как единое целое и имеющий определенную структуру, включающую как саму передаваемую информацию, так и служебные данные. Служебную информацию принято называть контрольной суммой. Она вычисляется по специальным алгоритмам на основе информационных данных, причем не обязательно в виде суммирования.

Будем считать для определенности, что при передаче протокольных единиц данных контролируются кадры. В этом случае контрольную сумму называют контрольной последовательностью кадра. (FCS, Frame Check Sequence). Передатчик отправляет контрольную последовательность кадра как часть PDU. Приемник на своей стороне вычисляет FCS по известному алгоритму и сравнивает с переданной контрольной последовательностью. Если FCS передатчика и приемника совпадают, то принимается решение, что передача данных по сети выполнена корректно.

Основными методами контроля данных (обнаружения ошибок) являются следующие:

  • — контроль по паритету;
  • — вертикальный и горизонтальный контроль по паритету;
  • — контроль контрольной суммой;
  • — контроль циклическим избыточным кодом.

Указанные методы отличаются друг от друга как вычислительной сложностью, так и способностью обнаруживать ошибки.

Контроль по паритету является наиболее простым и в то же время наименее мощным методом контроля. Он предназначен для обнаружения битовых ошибок данных. Его суть заключается в следующем. К информационным данным добавляется один контрольный бит (г = 1), который дополняет количество единичных бит до четного или нечетного значения. В первом случае говорят о контроле четности данных, во втором — о контроле нечетности. Соглашение о выборе вида контроля принимается заранее.

Для обнаружения ошибки все передаваемые биты блока (как информационные, так и контрольный) суммируются по модулю 2. При наличии ошибки в передаваемом блоке (как исходных, так и контрольном) результат суммирования будет отличаться от контрольного разряда, который был принят. Это свидетельствует о наличии ошибки. Однако, если ошибок было четное количество (две, четыре и т.д.), то такое искажение останется незамеченным. Из-за этой особенности данный метод контроля применяется к небольшим блокам данных, обычно байтам. В этом случае избыточность кода составляет 1/8, что является довольно значительным, поэтому в компьютерных сетях контроль но паритету используется редко.

Пример 5.3. Рассмотрим ситуацию нечетного контроля трех информационных бит. В этом случае кодовые слова будут состоять из 4 бит. Разрешенными кодовыми комбинациями будут следующие:

Пробелом отделен контрольный бит. ?

Пример 5.3 иллюстрирует два факта, верных для произвольного количества информационных бит:

  • 1. При контроле по паритету только половина кодовых комбинаций оказывается разрешенной (8 кодов из 16 возможных).
  • 2. Минимальное расстояние кода dmm = 2, т.е. возможно только обнаруживать битовые ошибки, по нс исправлять их.

Вертикальный и горизонтальный контроль по парит,егпу во многом похож на рассмотренный выше метод с тем отличием, что информационные данные представляются (располагаются) в виде матрицы. Строками этой матрицы являются отдельные байты данных. Контрольные биты данных добавляются как для каждой строки, так и для каждого столбца (рис. 5.1).

Бит паритета «р» (горизонтальный контроль) добавляется к каждому передаваемому символу. Бит паритета вертикального контроля рассчитывается для каждой

Вертикальный и горизонтальный контроль по паритету

Рис. 5.1. Вертикальный и горизонтальный контроль по паритету

позиции бита в символе. Вертикальные контрольные биты собираются в отдельный контрольный символ (байт).

Данный метод позволяет обнаружить большую часть ошибок кратности 2. В то же время он обладает еще большей избыточностью но сравнению с обычным контролем по паритету, поэтому в реальных СПД вертикальный и горизонтальный контроль по паритету почти не применяется.

Контрольная сумма представляет собой дополнительный код (см. пример 3.2) суммы всех байт кодового слова. Суммирование выполняется но модулю разрядности поля контрольного кода. Дополнение суммы происходит до нуля (до следующего за максимально возможным числом разрядной сетки, когда все разряды представляют собой двоичные единицы, например, FF).

Передатчик отправляет информационные данные и контрольную сумму. Прием- пик на своей стороне суммирует все байты или слова кадра,, включая контрольные биты. Суммирование выполняется по тому же модулю (разрядности поля контрольного кода). В результате должно получиться то же число 0 (следующее за FF). Отличие в значении позволяет сделать вывод, что при передаче была допущена ошибка.

Вычисление контрольных сумм является одним из самых простых способов контроля кадров (вероятность определения ошибок достигает 99,9%). При постоянной длине контрольного кода с увеличением количества информационных данных в одной PDU вероятность обнаружения ошибок снижается. Метод контрольных сумм применяется для выявления битовых ошибок.

Рассмотренные три метода обнаружения ошибок являются достаточно простыми как с алгоритмической точки зрения, так и в технической реализации. Однако все они не позволяют обнаружить пакетные ошибки заданной кратности. Для решения этой проблемы может быть применен метод циклического избыточного контроля.

Циклический избыточный контроль (Cyclic Redundancy Check, CRC) является популярным методом обнаружения ошибок в СПД и других задачах, где не требуется исправление пакетных ошибок, например, при записи данных на жесткие и оптические носители.

Суть метода CRC заключается в следующем. На передатчике формируется п-бит- нос кодовое слово, состоящее из к информационных и г проверочных бит (поле FCS). До передачи кадра все проверочные биты имеют значение 0. Кадр целиком (все п бит, включая и обнуленные проверочные) в виде двоичного числа делится за некоторый делитель Р. Остаток от деления по модулю 2 помещается в иоле FCS. На стороне приемника принятый кадр целиком делится на тот же делитель Р. Если остаток от деления на приемнике равен 0, то принимается решение, что ошибок при передаче данных не произошло, иначе данные считаются искаженными.

Число бит в кадре может быть достаточно большим. Например, стандартный кадр Ethernet имеет длину 1024 байт, т.с. число будет содержать 8096 бит.

В циклических кодах передаваемые кадры имеют определенную структуру, т.е. информационные и проверочные биты всегда располагаются на определенных местах. С целью упрощения кодирования и декодирования проверочные биты обычно располагают в конце блока. Каждый блок данных кодируется и декодируется независимо от других блоков.

При практической реализации CRC значения бит представляются в виде многочленов от некоторой фиксированной переменной х. Коэффициентами многочленов являются двоичные числа, которые соответствуют передаваемым битам. Например, блок данных 10011010 представляется в виде многочлена 7-й степени с коэффициентами 1, 0, 0, 1, 1,0, 1,0 соответственно, т.е. х 7 + х 4 + х 2 + х.

Операции в циклических кодах можно рассматривать как с точки зрения операций над двоичными числами, так и с точки зрения операций над полиномами. При вычислениях используют операции сложения и деления полиномов. Сложение осуществ-

Деление также выполняется обычным образом, только операция вычитания заменяется сложением по модулю 2:

В циклических кодах разрешенные комбинации имеют два важных с точки зрения реализации свойства:

  • 1. Для разрешенной комбинации циклический побитовый сдвиг приводит к разрешенной комбинации. Именно этот факт и послужил основой для названия метода.
  • 2. Все разрешенные комбинации (в полиномиальном представлении) делятся без остатка на некоторый полином Р(х).

Полином Р(х) называют образующим или порождающим полиномом. Вид образующего полинома определяется желаемой разрядностью остатка и способностью определять ошибки. Число проверочных бит обычно совпадает со степенью порождающего полинома. Младший и старший биты Р(х) должны быть равны 1. Имеются и другие требования к образующему полиному. Некоторые конкретные порождающие полиномы определены в стандартах международных организаций.

Алгоритм построения циклического кода (кодирование передаваемых данных) имеет следующий вид:

  • 1. Передаваемый ^-битовый блок данных умножается на число 2 Г . Данная операция равносильна умножению полинома D(x), соответствующему А:-битовой последовательности, на полином х г . В результате длина битовой последовательности увеличивается на г разрядов, причем эти последние г разрядов (блок FCS) заполнены нулями.
  • 2. Полученная последовательность бит (как информационных, так и проверочных) делится на образующий многочлен Р(х) с остатком Q(x). Количество разрядов остатка на единицу меньше, чем у Р(х).
  • 3. Полученный остаток Q(x) складывается с полиномом D(x)x r . Данная операция равносильна размещению в битах FCS коэффициентов полинома Q(x). Полученная новая битовая последовательность (кадр) Т(х) = D(x)x r +Q(x) и должна быть передана но сети.

Нетрудно видеть, что передаваемый кадр должен делиться на образующий полином без остатка. Действительно, если некоторое число (делимое) делится на делитель с остатком, то при вычитании остатка из делимого полученный результат будет без остатка делиться на делитель. Если, например, разделить в десятичной системе счисления 210 278 на 10 941, то получится остаток 2 399. Если вычесть полученный остаток из делимого (210278), то результат 207879 будет нацело (т.е. без остатка) делиться на 10941.

Пример 5.4. Рассмотрим передачу блока данных 1011101. Этому блоку соответствует полином D(x) = х 6 + х 4 + х 3 + х 2 + 1. Пусть в качестве образующего полинома выбран Р(х) = х 4 4- х 4- 1, которому соответствует число 10011. Количество проверочных бит совпадает со степенью полинома Р(х), т.е. г = 4, последовательность передаваемых данных будет содержать п = 7 4- 4 = 11 бит.

Выполним умножение полинома D(x) на полином х 4 :

что соответствует битовой последовательности 10111010000.

Произведем деление полинома D(x)x 4 на образующий полином:

Остаток от деления D(x)x x на Р(х) равен Q(x) = х 2 + х, что соответствует числовому значению 110, которое и будет размещено в поле проверочных бит (так как их количество г = 4, то будет размещено число ОНО).

Передаче подлежит кадр, который в виде полинома является суммой Т(х) = = D + Q(x) = х 10 И- х 8 + х 7 + х 6 + х л 4- х 2 4- х, что соответствует числовому значению 10111010110.

Осуществим проверку, выполнив деление Т(х) на Р(х):

Таким образом, если был получен кадр 10111010110, то принимается решение, что ошибок при передаче не произошло. В противном случае полагается, что в данных имеются искажения. ?

Рассмотренный метод циклического избыточного контроля обладает большей вычислительной сложностью, нежели контроль но паритету и применение контрольных сумм, но имеет гораздо более высокие диагностические возможности. Кодирование CRC позволяет обнаружить все битовые ошибки, все двойные, ошибки нечетной кратности, а также пакетные ошибки. Вероятность нахождения ошибок оценивается в 99,9984%. Избыточность метода считается невысокой. Например, кадр в 1024 бит может иметь контрольные данные размером в 4 бита, что составляет 0,4%.

Дальнейшим развитием метода циклического избыточного контроля является ЕСС-коитроль (контроль достоверности с исправлением ошибок, Error Correction Code), позволяющий не только обнаруживать, но и исправлять некоторые ошибки.

Конспект лекций «Компьютерные сети»

Компьютерная сеть — это совокупность компьютеров, которые могут обмениваться между собой информацией.

Компоненты компьютерной сети:

  • компьютер;
  • линии связи (коммуникационное оборудование) — техника, которая реализует возможность обмена информацией (провода, устройства, иногда — компьютер, выполняющий функцию коммуникационного оборудования);
  • операционная система, в особенности, модули ОС, реализующие сетевое взаимодействие;
  • распределенные приложения — программы, которые работают одновременно на разных компьютерах, например, WWW.

Сервер — компьютер или программа, предоставляющая некоторые услуги.

Выделенный сервер — это компьютер, служащий только для обслуживания клиентских машин. Доступ к нему обычно получают администраторы системы для выполнения задач управления, мониторинга и поддержки работоспособности. Часто они выполняют только какую-то одну задачу.

Клиент — это компьютер или программа, запрашивающая услуги.

Клиенты бывают толстыми, тонкими и сверхтонкими.

Сравнительные характристики клиентов

Данные хранятся на сервере
Программа-«сервер» хранится и работает на сервере
Программа-«клиент» (стандартное ПО, например, браузер) хранится и выполняется на клиенте
Данные обрабатываются на сервере
Интерфейс строится программой-«клиентом» на клиенте

При доступе к почте через почтовую программу, например, Mozilla Thunderbird по протоколу IMAP (данные хранятся на сервере, а интерфейс обеспечивается почтовой программой-клиентом) можно сказать, что интерфейс строится программой-клиентом на клиенте. Если используется протокол POP3 — речь идет уже о толстом клиенте. В случае же доступа к почте через веб-интерфейс (данные хранятся на сервере и интерфейс (веб-странички) генерируются сервером) интерфейс строится на сервере и передается программе-клиенту.

Протокол определяет:

  • формат сообщений;
  • очередность сообщений;
  • действия, которые необходимо выполнять при получении, приеме сообщений или при наступлении иных событий.

Пропускная способность канала связи (bandwidth) — наибольшая скорость передачи информации по каналу связи. Измеряется числом передаваемых двоичных символов в 1 с. Скорость передачи зависит от физических свойств канала связи, статистических свойств помех, способа передачи, приема сигналов и др..

  • EDGE — до 474 кбит/с
  • ADSL — 8 Mbit/s
  • FastEthernet — 100 Mbit/s
  • WiFi 802.11g — 54 Mbit/s
  • Gigabit Ethernet — 1000 Mbit/s

Особенности терминологии Internet – Интернет
internet — несколько локальных сетей (сетевой комплекс)
intranet – частная ceть организации, использующие механизмы Интернета
extranet – объединение intranet-сетей различных компаний через Интернет
Ethernet – технология локальных сетей

Интранет (англ. Intranet) — в отличие от сети Интернет, это внутренняя частная ceть организации. Как правило, Интранет — это Интернет в миниатюре, который построен на использовании протокола IP для обмена и совместного использования некоторой части информации внутри этой организации. Intranet допускает использование публичных каналов связи, входящих в Internet, (VPN — Virtual Private Network), но при этом обеспечивается защита передаваемых данных и меры по пресечению проникновения извне на корпоративные узлы.

Классификация компьютерных сетей

Классификация компьютерных сетей по территории
  • Local Area Network (LAN) — сети одной квартиры, дома, организации.
  • Metropolian Area Network (MAN), городские — высокоскоростные каналы связи в пределах большого города.
  • Региональные — объединяют компьютеры географической области.
  • Wide Area Network (WAN), глобальные.

Пример 1. Пользователи Spark объединены в локальную сеть, которую можно назвать городской (MAN).

Пример 2. Рунет — региональная сеть.

Пример 3. Интернет, сети магистральных Интернет провайдеров, сети организаций с филиалами по всему миру относятся к глобальным сетям.

Классификация компьютерных сетей по топологии

Общая шина
Полносвязные

Классификация компьютерных сетей по типу среды передачи
  • Проводные
    • витая пара;
    • коаксильный кабель;
    • оптоволокно.
    • радиосвязь (WiFi, WiMAX);
    • инфракрасная связь;
    • СВЧ-связь (Bluetooth).

    Пример. Сеть мехмата имеет топологию дерево.
    Cеть мехмата. Красные линии – оптоволокно, синие – витая пара

    Файлообменные P2P сети

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

    В случае пиринговой (peer to peer — от равного к равному) организации обмена данными такого сервера нет. В P2P-сети пользователи скачивают информацию друг у друга, а не у выделенного сервера. Выглядит это так: пользователи сети выкладывают какие-либо файлы в «расшаренную» (англ. share, делиться) папку, т. е. папку, файлы из которой доступны для скачивания другим клиентам. Какой-нибудь другой пользователь сети посылает запрос на поиск какого-либо файла. Программа ищет у клиентов сети файлы, соответствующие запросу, и показывает результат. После этого пользователь может скачать файлы у найденных источников.

    Современные файлообменные сети позволяют скачивать один файл сразу с нескольких источников (так быстрее и надёжнее). Чтобы убедиться, что этот файл у всех источников одинаковый, производится сравнение не по названию файла, а по контрольным суммам или хэшам типа MD4, TTH, SHA-1. Во время (и после) скачивания файла пользователем, этот файл у него могут скачивать и другие клиенты сети, в результате чего файлы могут в итоге быть доступными для скачивания со многих источников одновременно.

    Схема работы P2P-сети с централизованным каталогом

    P2P-сети с централизованным каталогом. Napster

    Когда пир (пользователь P2P-сети) подключается к серверу, он сообщает свой IP и имеющиеся файлы. На сервере собираются не сами файлы, а информация о них. Пользователи посылают запросы на поиск какого-либо файла центральному серверу, который им говорит у кого искомые файлу есть.

    Самый известный пример P2P-сети с централизованным каталогом является сеть Napster.

    Историческая справка. Napster

    Napster — служба обмена mp3-файлами, созданная Шоном Фаннингом (Shawn Fanning) – 18-летним студентом ( Napster – это его ник). Она использовалась в основном студентами для обмена музыкой и стала очень популярной (80% интернет трафика). Она проработала с 1999 по 2001. В июле 2001 центральный каталог на сервере был закрыт по решению суда, несмотря на то, что файлов на сервере не было. Иск подавала Recording Industry Association of America (RIAA) — Американская ассоциация звукозаписывающих компаний.

    Частично децентрализованные сети

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

    eDonkey

    eDonkey (eDonkey2000, eD2k, осел, ослик) была создана Джедом Мак Калебом, вышла в сентябре 2000 г. По сравнению с Napster у нее появилось несколько нововведений: множественная закачка (когда клиент может закачивать файл по частям, причем разные части у разных пиров). У Napster серверы, на которых хранится централизованный каталог, не связываются между собой. В последних версиях eDonkey200 0 серверы формируют поисковую сеть (каждый сначала ищет у себя, потом у других). Вместо имен файлов у Napster в eDonkey для идентификации используются хэш-суммы . Таким образом, один и тот же файл, имеющий разные имена у пиров, трактуется сервером как один файл.

    Каждый клиент связан с одним из серверов сети. Клиент сообщает серверу, какие файлы он предоставляет в общий доступ. Каждый сервер поддерживает список всех общих файлов клиентов, подключенных к нему. Когда клиент что-то ищет, он посылает поисковый запрос своему основному серверу. Периодически серверы связываются друг с другом на короткое время. Во время этого сеанса связи сервер, объявляя о своём существовании, посылает список всех других известных ему серверов. Таким образом, серверы поддерживают список других активных серверов. Когда клиент подключается к серверу, сервер может выдать ему список известных ему серверов.

    Принцип работы: клиент Z имеет все части файла (символы строчных букв представляют части файла). Клиенты W, X, и Y хотят загрузить Файл. Клиенты X и Y имеют различные части файла, они могут не только получить файл от клиенты Z, но могут и посылать файл друг другу. Это позволяет файлу быть распределённо распространённым намного быстрее без того, чтобы использовать большее количество ширины канала клиента Z. Клиент W может запустить загрузку файла, даже если источник файла (Z) больше не имеет достаточной ширины канала для отсылки.

    eDonkey сейчас

    В феврале 2006 прекратил работу самый популярный сервер сети eD2k — Razorback, и была прекращена разработка коммерческого клиента EDonkey2000. Причиной «закрытия» сети послужил иск RIAA на 30 миллионов долларов.

    Закрытие eDonkey вызвало большой ажиотаж по очень простой причине — этот файлообменник в последние годы был одним из крупнейших. Им пользовались 2-3 миллиона человек, которые чувствовали себя в относительной безопасности. Среди этих пользователей нашлись такие, которые еще в 2002 году решили создать альтернативный клиент, который бы использовал сеть eDonkey и развитие которого при этом не зависело бы от существования компании MetaMachine. Этот клиент называется eMule и очень популярен, в частности, у российских интернетчиков. Он, в отличие от eDonkey, умирать не собирается. Более того, сторонники eMule считают, что поддерживаемый eMule протокол Kad (вариант протокола Kademlia) обеспечивает достаточную анонимность для безнаказанного получения любых файлов. Свежая версия eMule к тому же умеет маскировать обмен файлами от провайдеров.

    BitTorrent

    Отличия от eDonkey: более централизованный. Протокол BitTorrent требует фиксирования каждой такой загрузки на tracker-сервере, даже если сервер в транзакции не участвует. В случае отсутствия в сети tracker-сервера файл загрузить нельзя. Внедрение tracker-сервера позволяет проследить за статистикой загрузок (что немаловажно для софтверных компаний).

    Историческая справка. Дистрибутивы Linux в сети BitTorrent

    Услугами BitTorrent воспользовались такие компании, как Red Hat и Mandrake, выложив в сеть новые версии своих операционных систем с одновременной публикацией на сайте torrent-файлов. Дистрибутивы представляли собой три ISO-файла объемом около 700 МВ каждый, т. е. в итоге любители Linux были вынуждены загружать около 2 GB, что в былые времена «убивало» FTP-серверы. По словам представителей Red Hat, после запуска дистрибутивов в сеть BitTorrent нагрузка на центральный FTP-сервер компании упала на 99%. Более того, присутствие tracker-сервера позволило Red Hat отследить статистику загрузок в режиме реального времени. Подробная информация редко доступна или принципиально невозможна в других пиринговых сетях.

    Полностью децентрализованные сети

    Gnutella — это пример полностью децентрализованные сети.

    Gnutella

    Историческая справка. История появления

    Эту сеть началa создавать America Online с корыстными целями. Собрали одних из лучших сетевых программистов, которые придумали непобедимое чудо сетевых технологий. Но, так получилось, что AOL объединился со звукозаписывающей компанией и понял, какую собаку он себе подложил. Сеть попытались закрыть, но она оказалась непобедимой, плюс, непосредственно создатели сопротивлялись. От AOL они ушли, и стали строить эту сеть сами. Вот так AOL навредил самому себе.

    Gnutella построена по собственной особой технологии без центральных узлов gPulp. Узлами здесь служат сами пользователи, а саму программу вывести из строя невозможно. Работа сети: 1 шаг: To envision how Gnutella originally worked, imagine a large circle of users (called nodes), who each have Gnutella client software. On initial startup, the client software must bootstrap and find at least one other node. далее: Once connected, the client will request a list of working addresses. The client will try to connect to the nodes it was shipped with as well as nodes it receives from other clients until it reaches a certain quota. It will only connect to that many nodes, locally cache the addresses it has not yet tried and discarding addresses it tried which were invalid. поиск: Пользователь вводит запрос (например, название mp3-файла). Программа рассылает запрос на поиск файла всем узлам в списке, а далее просто ждет входящих сообщений. Каждый узел, получивший запрос на поиск, ищет в своем фонде указанный файл. Если файл не найден, то узел просто не отвечает. Если файл найден, узел отсылает инициатору запроса ответ с информацией о файле и о себе (IP-адрес). Получив ряд ответов, программа выбирает один из узлов, устанавливает с ним стандартное HTTP-соединение и загружает файл. При этом все сообщения (от Ping-запроса до скачивания файла) посылаются по HTTP, что затрудняет их отслеживание и блокировку.

    При этом зависимость загрузки каналов от числа узлов экспоненциальная. Действительно, пусть компьютер хочет опросить все компьютеры в сети. Он посылает запрос 10 известным ему компьютерам. Каждый из них отправит по 10 запросов известным им компьютерам и т.д.. Итого получится 10+100+1000+..+10^d запросов, где d-расстояние до самого далекого компьютера. Таким образом, если количество компьютеров в сети увеличится в 2 раза, то увеличится количество запросов, примерно, возведётся в квадрат.

    Now, when the user wanted to do a search, the client would send the request to each node it is actively connected to. The number of actively connected nodes for a client was usually quite small (around 5), so each node then forwards the request to all the nodes it is connected to, and they in turn forward the request, and so on, until the packet was a predetermined number of «hops» (прыжков) from the sender.

    If a search request turns up a result, the node that had the result needs to contact the searcher. In the classic Gnutella protocol response messages were always sent back along the route the query came in through, as the query itself did not contain identifying information of the node. This scheme was later revised, so that search results are delivered over UDP directly to the node which initiated the search, respectively a proxying peer, usually an ultrapeer of the node. The queries do therefore carry the IP address and port number of either node. This lowers the amount of traffic routed through the Gnutella network, making it significantly more scalable.

    In practice, this method of searching on the Gnutella network was often unreliable. Each node is a regular computer user; as such, they are constantly connecting and disconnecting, so the network is never completely stable. Also, the bandwidth cost of searching on Gnutella would grow exponentially to the number of connected users, often saturating connections rendering slower nodes useless. Therefore, search requests would often be dropped, and most queries reached only a very small percentage of the network. This observation identified the Gnutella network as an unscalable distributed system, and inspired the development of distributed hash tables, which are much more scalable but support only exact-match, rather than keyword, search.

    Апгрейд: To address the problems of bottlenecks, Gnutella developers implemented a tiered system of ultrapeers and leaves. Instead of all nodes being considered equal, nodes entering into the network were kept at the ‘edge’ of the network as a leaf, not responsible for any routing, and nodes which were capable of routing messages were promoted to ultrapeers, which would accept leaf connections and route searches and network maintenance messages. This allowed searches to propagate further through the network, and allowed for numerous alterations in the topology which have improved the efficiency and scalability greatly.

    Полностью децентрализованные сети

    DHT (Distributed hash table) — децентрализованная распределенная система для объединения большого количества постоянно исчезающих и появляющихся узлов и эффективной передачи сообщений между ними. Она использует 160-битные хэши для идентификации узлов, файлов и имен файлов (ключевых слов). Каждый узел содержит информацию о месторасположении файлов с хешами, близкими к его хешу.

    Поиск в Kad. Кружочками отмечены узлы.

    Kad

    Сеть Kad — это реализация DHT. Узлы, файлы и имена файлов (ключевые слова) кодируются алгоритмом SHA-1 160-битными числами. Если узел хочет расшарить файл, он обрабатывает его, получая хэш, который идентифицирует этот файл в сети. Затем узел ищет несколько узлов, ID которых близки к хэшу файла и его имени (размеры хешей файлов и узлов совпадают, расстояние вычисляется применением операции XOR к хешам). На эти узлы отдается информация об адресе узла, на котором хранится файл.

    Поиск в Kad

    В соответствии с хешами узлы можно разместить в двоичном дереве.

    Поиск очень похож на DNS-запросы. Каждый узел (как и каждый DNS-сервер) знает адреса всех узлов в своей ветке, расположенных рядышком (на этом же уровне или ниже (зон следующего уровня или дочерних зон в DNS)) и адреса некоторых узлов «высокого уровня».

    Когда узел хочет найти файл, он сравнивает хеш имени с хешами известных ему узлов, затем посылает запрос тому узлу, чей хеш наиболее близок к искомому. Тот узел возвращает ему адрес узла, чей хеш ещё ближе к искомому. Тогда наш узел посылает запрос тому новому узлу, и получает от него адрес следующего узла, чей хеш ещё ближе и т.д.. Таким образом, запросы постепенно стекаются к узлам, чьи хеши наиболее похожи на искомый. А эти узлы уже знают, где находится файл. Запросы итеративные. «Стоимость» такого поиска логарифмически зависит от количества узлов в сети и, если количество узлов удвоится, количество запросов возрастет на 1.

    Другие приложения P2P-сетей

    • мобильный P2P;
    • распределенные вычисления SETI@home;
    • совместное работа ( Groove );
    • Skype.

    Структура сети Интернет

    Локальные, региональные, магистральные провайдеры

    Локальный (местный) провайдер (ISP – Internet Service Provider) – поставщик услуг Интернета, работающий (как правило) в пределах одного города (ЮГИНФО, ЦТС, Интеркабель).

    Региональный провайдер – одной страны, области, округа (ТрансТелекомКавказ, ЮТК, ЦТС).

    Магистральный провайдер – страны, континента, земного шара (Global one Orange), Голден Телеком, Ростелеком, Verizon, Cogent)

    Точки присутствия (POP), точки обмена трафиком (IX)

    Ядро Интернета (или Core Backbone Network) составляют сети так называемых провайдеров первого уровня (Network Server Provider Tier-1) или магистральных провайдеров, наиболее крупными из которых являются UUNET(куплен Verizon), AT&T(в Америке), MCI (куплен Verizon), GTE/BBN (вместе с AT&T в SBC) и Sprint (названия часто меняются, из-за того что одни фирмы объединяются, другие кого-то покупают или входят в состав более крупных фирм, третьи переименовываются).

    Эти сети построены в основном на базе технологий SONET/SDH, DWDM, ATM. Для их магистралей характерны каналы 622 и 2488 Мбит/с соответственно. Иногда встречаются каналы 9952 Мбит/с и даже более.
    Сети магистральных провайдеров первого уровня свободно обмениваются между собой трафиком через IXP – Internet Exchange Point точки обмена трафиком. Страны получают доступ к ядру Интернета либо благодаря магистральным провайдерам первого уровня, имеющим точки присутствия (POP-Point of Presence) по всему миру, либо локальным магистральным провайдерам первого уровня. Сети NSP Tier-1 свободно обмениваются между собой трафиком, причем основная часть этого обмена сосредоточена в двух зонах (Metropolian Exchange Area,MAE), расположенных в Нью-Йорке и Сан-Франциско. Хотя наибольшая концентрация NSP первого уровня приходится на США, «ареал распространения» этих сетей не ограничивается только этой страной. Другие страны получают доступ к ядру Интернета либо благодаря NSP первого уровня, имеющим точки присутствия (POP-Point of Presence) по всему миру (например, UUNET «дотягивается» и до Европы, и до Юго-Восточной Азии), либо локальным NSP первого уровня (эта практика распроcтранена в Азии).

    Ниже магистральных провайдеров по иерархии расположены сетевые провайдеры следующего уровня — региональные, соединенные между собой высокоскоростными каналами передачи данных, которые, в свою очередь предоставляют доступ к Интернету местным (локальным) провайдерам (Internet Service Privider, ISP). Индивидуальные пользователи и компании-клиенты получают доступ к ресурсам Интернета именно при помощи ISP. Соединение между ISP и пользователями (частными или корпоративными) обычно осуществляется при помощи: коммутируемых линий (обычных телефонных или ISDN), спутниковой связи, ADSL, VDSL, WiMAX, мобильной связи (2G, 2.5G, 3G) или посредством так называемых выделенных линий: FTTH (Fiber to the Home), ETTH (Ethernet to the Home).

    Таким образом, путь между произвольным Web-сервером и компьютером пользователя состоит из трех основных частей — участка между Web-сервером и скоростной магистралью, участка скоростной магистрали и участка, связывающего пользователя с магистралью.

    На связистком жаргоне первый участок обычно называют «первой милью«, а третий — «последней милью«.

    Недостаточная скорость передачи данных может создать неприятности как на первой, так и на последней миле. Однако проблемы первой мили решаются довольно просто — надо перевести сервер из офиса компании в серверный центр, который непосредственно подключен к магистрали. Эта услуга называется collocation.

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

    Point Of Presence (POP), точка присутствия – место расположения оборудования оператора связи (провайдера), к которому возможно подключение клиентов.

    Обычно, POP – это узел связи или датацентр, возможно, отдельная единица коммуникационного оборудования, вынесенная ближе к месту концентрации потенциальных клиентов, например, в офисное здание. Данный термин применяется при планировании сетей передачи данныхм и расчёте их стоимости. Обычно провайдер, оказывающий услуги по подключению к сети или передаче данных, указывает стоимость своих услуг именно в точке присутствия. Для определения же полной стоимости следует учесть построение (аренду) и эксплуатацию канала связи от точки присутствия до оборудования клиента (так называемой, последней мили). Поэтому при планировании сетей территориальное расположение точек присутствия различных провайдеров имеет не меньшее значение, чем стоимость и технические характеристики их услуг.

    Например, при предоставлении услуги подключения к сети Интернет последняя миля — участок от порта коммутатора провайдера на его узле связи до порта маршрутизатора клиента в его офисе. Для услуг коммутируемого (dial-up, диалапного) подключения последняя миля — это участок между модемом пользователя и модемом (модемным пулом) провайдера. В последнюю милю обычно не включается разводка проводов внутри здания. К технологиям последней мили обычно относят xDSL, Wi-Fi, WiMax. К оборудованию последней мили можно отнести xDSL-модемы, мультиплексоры доступа, оптоволоконные модемы и преобразователи, радиомультиплексоры. Есть специализированные компании и подразделения крупных компаний связи, которые занимаются исключительно построением последней мили.

    В России и многих других странах именно последняя миля сдерживает расширение аудитории Интернета, внедрение новых технологий, предоставление новых телекоммуникационных услуг. Дело в том, что последняя миля, как правило, является самым «узким» участком канала от пользователя до поставщика услуг. Расширить же этот канал стоит достаточно дорого из-за рассредоточенности пользователей.

    IXPnternet eXchange Point (IXP), точка обмена трафиком – инфраструктура, которая позволяет различным провайдерам обмениваться трафиком.

    Создаются для беспрепятственного пропускания трафика между различными провайдерами без загрузки внешних магистральных каналов. В местах, где дальняя связь плохо развита, местные региональные операторы оплачивают трафик во много раз дороже, чем операторы в США или Европе. Поэтому они организовывают точки обмена трафиком, через которые и пропускают крайне дешёвый трафик между своими клиентами.

    Коммутация каналов и коммутация пакетов

    Коммутация каналов

    В 60-х годах основным средством связи были телефонные линии, использующие принцип коммутации каналов.

    Они имели существенный недостатотк: нельзя освободить канал в период простоя. Под каждый сеанс разговора между двумя абонентами выделяется отдельный канал на всем протяжении линии. Он устанавливается в момент соединения и занят, пока есть соединение. Если нет свободных каналов, то линия становится перегруженной.

    Основные способы организации каналов, по которым могут разговаривать много пользователей:

    • частотное мультиплексирование (разделение) — для каналов выделяются частотные поддиапазоны. Например, этот метод используется в технологии X-DSL. По кабелю передаются сигналы различной частоты: телефонный разговор-0,3-3,4 Кгц а для передачи данных используется полоса от 28 до 1300 Кгц.
    • временное мультиплексированиемультиплексирование — используются все частоты, но в определенное время, т.е. канал используется попеременно каждым абонентом. Вся пропускная способность выходного канала предоставляется в течение фиксированных интервалов времени каждому входному каналу. Недостаток: даже если какой-то входной канал не использует для передачи выделенный ему интервал, другие каналы не могут передавать данные в это время.
    Коммутация пакетов

    Сообщение разбивается на пакеты, которые могут идти независимо друг от друга (по разным маршрутам). В случае когда пакетов много, организуются очереди. Исключение: в сетях с режимом асинхронной передачи (Asynchronous Transfer Mode, ATM) коммутация каналов сочетается с коммутацией пакетов (см. главу 5 Куроуза и Росса).

    Историческая справка. История развития сети Интернет

    1969 г. Рождение ARPAnet

    Леонард Клейнрок рядом с первым интерфейсным процессором сообщений (коммутатором пакетов)

    Леонард Клейнрок — один из авторов технологии коммутации пакетов. Он открыл возможность совместного использования эфира независимыми узлами сети.

    Alohanet — первая радиосеть с коммутацией пакетов.

    Request for Comments, RFC — документ из серии пронумерованных информационных документов Интернета, содержащих технические спецификации и стандарты, широко применяемые во всемирной сети. Формат RFC появился в 1969 году при обсуждении проекта ARPANET. RFC 1 был опубликован 7 апреля 1969 г. и назывался «Host Software». Первые RFC распространялись в печатном виде на бумаге в виде обычных писем, но уже с декабря 1969 г., когда заработали первые сегменты ARPANET, документы начали распространяться в электронном виде. Несмотря на название, запросы комментариев RFC сейчас рассматриваются как стандарты Интернета (а рабочие версии стандартов обычно называют драфтами, от англ. draft здесь — черновик). Примеры популярных стандартов: IP, UDP, TCP, HTTP, SMTP, FTP, DNS, URL, NAT… Есть первоапрельские RFC, например, RFC 1149 «Internet Protocol посредством почтовых голубей» (между прочим, реализованный на практике).

    В ARPAnet взаимодействие между компьютерами было многосоставным: модемы (IMP) общались между собой по своим правилам, использующим маршрутизацию пакетов, контроль потока и осуществляющим надежную передачу пакетов; существовало ПО для передачи информации между модемом и компьютером; поверх этих программ работала NCP — Network-Control Program (RFC 001) — программа для обмена информацией между компьютерами. Адреса в NCP включали в себя идентификатор пользователя, компьютера и соединения между программами (прообраз сокетов). В марте 1972г с использованием функций NCP были написаны первые сетевые программы электронной почты SNDMSG and READMAIL (электронная почта между пользователями мейнфреймов на самом деле родилась раньше) В июле 1972 вышел стандарт RFC 354 службы передачи файлов FTP, используемой повсеместно и сегодня.

    ALOHAnet Одним из первых обитателей будущей Кремниевой Долины, увлекшимся созданием сетей, оказался профессор из Стэнфорда Норм Абрамсон. Так оказалось, что он был еще и заядлым серфингистом. Совместить две области интересов ему удалось на Гавайских островах, где, как известно, одно из лучших в мире мест для катания на доске, а компьютеры, находившиеся в ведении местного университета, были разбросаны по нескольким островам архипелага. Так вот, Абрамсон предложил связать их сетью с использованием радиоканалов. Это было сделано в 1970 году. На решение о создании сети в немалой степени повлияло личное знакомство Абрамсона с Робертсом. Впоследствии Абрамсон смог получить процессоры IMP и по радио подключить созданную им сеть Alohanet к ARPAnet. Сеть, названная по имени самого крупного из островов, оказалась первой радиосетью с коммутацией пакетов. Но самое большое достижение Абрамсона состояло в том, что он открыл возможность совместного использования эфира независимыми узлами сети. В первой версии протокола идея Абрамсона была интригующе простой: «Если у вас есть данные для передачи — передавайте, а если обнаружите, что частота занята… то подождите и пошлите позже». Суть идеи заключена именно в формулировке «пошлите позже»; сегодня о ней мало кто задумывается, а тогда она надолго захватила умы инженеров. В последующем схема был доведена до совершенства Робертом Меткалфом, автором Ethernet, и получила название «множественный доступ к среде с контролем несущей и обнаружением коллизий» (Carrier Sense Multiple Access with Collision Detection, CSMA/CD). Непосредственными преемниками Alohanet стали протокол Slotted Aloha, а позже — протоколы популярных беспроводных сетей передачи данных ARDIS, Mobitex, CDPD и даже GSM.

    1970-1980 гг. Возникновение новых компьютерных сетей и Интернета

    Параллельно с развитием ARPAnet появлялись другие компьютерные сети: ALOHAnet (радио сеть Гавайского университета, Telenet, Cyclades (во Франции), SNA и др. Возникла задача о соединении сетей с различной архитектурой. Нужно было придумать новую систему адресации компьютеров, которая бы работала для объединенной сети — Интернета. Старый протокол NCP был больше похож на драйвер устройства.

    Роберт Канн совместно с Уинтоном Серфом разработал новую версию протокола, которая впоследствии была названа TCP/IP (Transmission Control Protocol, протокол управления передачей данных; IP — Internet Protocol). Изначально это был один протокол TCP, который осуществлял маршрутизацию и надежную доставку пакетов, использовал глобальную адресацию компьютеров. Эксперименты с пакетной передачей голосовых сообщений показали, что иногда требуется, чтобы протокол допускал потерю некоторых пакетов при передаче информации. Это привело к появлению протокола IP, несущего транспортные функции и протоколов TCP и UDP (User Datagram Protocol) для надежной и ненадежной передачи данных.

    Еще одним выходцем из «могучей кучки» МТИ был француз Луи Пуссен. В середине 60-х он участвовал в разработке операционной системы Multics; ему принадлежит авторство термина shell для обозначения языка управления, используемого сегодня во многих операционных системах. А в начале 70-х с группой коллег он снова побывал в США и ознакомился с состоянием дел ARPAnet. Итогом этого визита стали несколько отчетов, стимулировавших французское правительство к финансированию работ по созданию собственной сети, получившей название Cyclades Packet Switching Network. Тогда во Франции активно развивались собственные сетевые решения, приведшие в частности к созданию уникальной телефонной сети с терминалами minitel, предоставлявшимися абонентам бесплатно. Под натиском Internet сеть Cyclades в середине 80-х прекратила свое существование, однако ее, как и Alohanet, нельзя рассматривать как тупиковые ветви. Из проекта Cyclades непосредственным образом вырос протокол TCP/IP. Сеть Cyclades была многоуровневой: первый уровень — уровень передачи данных (Data Transmission), второй — транспортный (Transport), третий — прикладной (Application). Авторы TCP/IP, Винт Серф и Роберт Канн ссылаются на Пуссена, как на своего предшественника.

    1980-1990 гг. Распространение компьютерных сетей

    Разработана система доменных имен DNS (Domain Name System), связавшая IP адреса компьютеров с их мнемоническими именами

    Середина 80-х. Создание NFSnet (сеть национального научного фонда США (NFS)

    Основой сети NFSNET стали пять очень мощных компьютеров, соединенных между собой сверхбыстрыми (на тот момент) линиями связи. Пользователи подключались к сети и использовали мощности этих компьютеров. NFSNЕТ унаследовала от ARPANET принципы построения, обеспечивающие высокую надежность, а также три уровня протоколов (под протоколом в данном случае понимается соглашение о способе передачи информации; понятно, что если разные части сети будут использовать разные способы передачи, то они друг друга просто не поймут) — сетевой, транспортный и протокол приложений, а также добавила к ним протокол межсетевого уровня под названием IP (интернет-протокол). Полученный комплект протоколов получил название TCP/IP — как раз на нем-то и базируется передача информации в Интернете.

    Сеть NFSNET была более прогрессивной и предоставляла намного более мощные возможности по сравнению с ARPANET, поэтому ARPANET была ликвидирована в конце восьмидесятых. NFSNET заняла место прародительницы Интернета, а это потребовало ее умощнения и некоторой реорганизации, в результате чего был создан так называемый Бекбон NFSNET (от англ. backbone — хребет), который состоял уже из тринадцати компьютеров (точнее, компьютерных центров), соединенных друг с другом теми же высокоскоростными линиями связи. Центры располагались в разных городах США и, по сути, являлись одновременно центрами местных компьютерных сетей, так что NFSNET стала сетью, объединяющей другие сети.

    Тим Бернерс-Ли

    1990 г. Ликвидирована ARPAnet

    90-е годы. WWW

    Тим Бернерс-Ли вместе со своими ассистентами создает первоначальную версию языка разметки гипертекста HTML, протокола HTTP передачи HTML-документов, web-сервера и браузера.

    Многоуровневые сетевые модели

    Глобальные сети объединяют в себе огромное количество географически распределённых узлов. Множество вариантов программно-технической реализации передачи информации породили необходимость создания открытых стандартов — стандартов, официально опубликованных и доступных для разработчиков программно-аппаратных компонентов.

    Взаимодействие уровней

    Взаимодействие приложений через сеть очень сложно. Разделение его на уровни позволяет понизть сложность. Каждый уровень взаимодействует через сеть с одноименным уровнем. Для этого уровень пользуется услугами нижележащего уровня и каждый уровень предоставляет услуги вышележащему уровню.

    Благодаря такой структуре совместная работа сетевого оборудования и программного обеспечения становится гораздо проще и понятнее.

    Сетевая модель

    Сетевая модель определяет:

    • службы — то, что делается на данном уровне;
    • интерфейсы (API) — как обращаться к другим уровням;
    • протоколы — набор правил общения с одноуровневым компонентом на другом узле сети.
    Как устроена сетевая модель

    Каждый сетевой уровень подчиняется определенному сетевому протоколу, определяющему набор сетевых служб, присущих данному уровню.

    Сетевая служба — это набор функций, которыми обладает определенный сетевой уровень, выполняемых для вышележащего уровня (например, коррекция ошибок).

    Каждый сетевой уровень запрашивает определенную сетевую службу от нижележащего уровня. Протокол уровня определяет структуру данных и формат пакета для выполнения запрашиваемой сетевой службы.

    Протокол — это правила, которым должен следовать уровень, чтобы реализовать сетевую службу.

    Сетевой протокол описывает формат данных или пакетов данных, то есть правила оформления, которым данные должны подчиняться, чтобы программное обеспечение выполняло ту или иную функцию или сетевую службу (для случая коррекции ошибок протокол описывает какие ошибки сетевая служба должна исправлять).

    Пример. Почтовая служба. Чтобы отправить кому-либо письмо, мы пишем адрес на кон-верте. Таким образом, функция адреса заключается в обеспечении правильной доставки. Формат, в котором пишется адрес, строго определен: 1-я строка – кому, 2-я строка – улица, дом, 3-я строка – город. Почтовые работники ожидают, что на второй строке будет указана улица, а за ней – номер дома. Формат адреса на конверте следует определенному протоколу.

    Пример трехуровневой модели. Архитектура «философ — переводчик — почта»

    Пример трехуровневой модели

    Философы используют функции нижележащих уровней: переводчиков и почты. Они непосредственно общаются с переводчиками. Переводчики переводят сообщение, затем оно отправляется по почте.

    Передача сообщения

    Передача сообщения

    При передаче, информация делится на пакеты. Фактически, передаваемая информация формируется на самом верхнем уровне — уровне работающего приложения (прикладном). Далее пакет «спускается» по уровням модели и на каждом из них получает свой заголовок и концевик. Этот заголовок содержит функционально-специфичную для данного уровня информацию о пакете (например, адрес). При получении информации узлом-получателем большой (с заголовками всех уровней) блок информации начинает обрабатываться в обратной, восходящей, последовательности уровней, причём на каждом уровне происходит анализ и отщепление соответствующего заголовка. Таким образом, до процесса-получателя доходит исходный передаваемый блок. На уровнях зачастую сообщение M вместе с заголовками от верхних уровней подвергается изменениям: шифрованию, сжатию, разбиению на части,…, поэтому изображенная картинка с одной и той же часть M, вообще говоря, не совсем правильная (зато понятная).

    Пример. Вспомним беседу философов. Переводчик хинди-английский переводит исход-ное сообщение философа, дополнительно делая пометки о значениях слов. Далее, на почте это письмо запечатывается в конверт, на конверте пишется соответствующая информация (об отправителе и получателе). На почте в Голландии конверт распечатывается, и письмо передается переводчику английский-голландский. Используя сделанные коллегой помет-ки, переводчик восстанавливает на голландском содержимое письма. Письмо передается голландскому философу.

    Модель OSI имеет семиуровневую структуру, и можно говорить о взаимодействии узла-отправителя и узла-получателя на каждом уровне модели.

    Функции уровней

    В компьютерной сети каждый уровень может выполнять одну или несколько функций, перечисленных ниже.

    • адресация,
    • правила переноса данных: направление переноса (например, только в одном направлении или в любом направлении), логические каналы (например, специальный канал для «срочных» данных),
    • контроль ошибок,
    • соблюдение последовательности пакетов,
    • управление потоком сообщений (быстрый не зафладит медленного),
    • мультиплексирование: объединение несвязанных пакетов для совместной передачи на одном из уровней (например, на физическом уровне мультиплексирование чаще всего неизбежно, так как вся связь осуществляется по ограниченному числу контуров),
    • маршрутизация.
    Эталонная модель OSI

    Эталонная модель взаимодействия открытых систем, Open Systems Interconnection Reference Model (OSI), создавалась как единый международный стандарт сетевых технологий.

    Набор протоколов называется открытым, если описание и детали протоколов опубликованы.

    Система, реализующая открытые протоколы называется открытой системой, несмотря на то, что код программ может быть закрыт.

    ISO — международная организация по стандартизации.

    OSI ISO — абстрактная модель для сетевых коммуникаций и разработки сетевых протоколов. Представляет уровневый подход к сети. Каждый уровень обслуживает свою часть процесса взаимодействия. Благодаря такой структуре совместная работа сетевого оборудования и программного обеспечения становится гораздо проще и понятнее.

    Существует 7 уровней с помощью которых происходит сетевое взаимодействие. От нижнего уровня к верхнему:

      Физический (Physical Layer) Передача битов данных по сети.

    • характеристики сигналов;
    • среды передачи;
    • физическую топологию среды передачи;
    • механические и физические (электрические, оптические) спецификации среды передачи;
    • интерфейсы (разъемы) оборудования.

    Физический уровень занимается реальной передачей необработанных битов по каналу связи. При разработке сети необходимо убедиться, что когда одна сторона передает единицу, то принимающая сторона получает также единицу, а не нуль. Принципиальными вопросами здесь являются следующие: какое напряжение должно использоваться для отображения единицы, а какое — для нуля; сколько микросекунд длится бит; может ли передача производиться одновременно в двух направлениях; как устанавливается начальная связь и как прекращается, когда обе стороны закончили свои задачи; из какого количества проводов должен состоять кабель и какова функция каждого провода. Вопросы разработки в основном связаны с механическими, электрическими и процедурными интерфейсами и с физическим носителем, лежащим ниже физического уровня.

    • взаимодействие со средой передачи данных (протокол MAC);
    • надежная доставка;
    • управление потоком.

    В протоколах канального уровня заложена определенная структура связей между компьютерами и способы их адресации. Для идентификации компьютеров на канальном уровне используются аппаратные адреса (MAC – адреса) в Ethernet. 802.Xx – номера описаний стандартов IEEE (институт инженеров по электротехнике и радиоэлектронике).

    Технологии: Ethernet (802.3), WiFi (802.11), Token Ring (802.5) и РРР.

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

    Протокол MAC (Media Access Control — управление доступом к носителю) определяет правила передачи кадра в линию. Для двухточечных линий с единственным отправителем на одном конце и единственным получателем на другом конце линии протокол MAC очень прост (или вообще отсутствует) — отправитель может передать кадр в любой момент, когда линия свободна. Более интересный случай представляет конфигурация, в которой несколько узлов совместно используют один широковещательный канал. В этом случае возникает так называемая проблема коллективного доступа, и протокол MAC призван координировать передачу кадров многих узлов.

    Надежная доставка. Когда протокол канального уровня предоставляет услугу по надежной доставке, он гарантирует перемещение каждой дейтаграммы сетевого уровня по линии связи без ошибок. Вспомним, что некоторые протоколы транспортного уровня (например, TCP) также обеспечивают надежную доставку. Аналогично службе надежной доставки транспортного уровня, служба надежной доставки канального уровня поддерживается с помощью механизмов подтверждений и повторных передач (см. раздел «Принципы надежной передачи данных»). Служба надежной доставки транспортного уровня часто обслуживает линии связи с высокой вероятностью ошибок, характерной, например, для беспроводных линий связи. Таким образом, на канальном уровне ошибки исправляются локально — на той линии связи, на которой они возникают, что позволяет отказаться от повторной передачи данных протоколом транспортного или прикладного уровня. Однако в линиях с низкой вероятностью ошибок надежная доставка на канальном уровне может оказаться излишней. К таким линиям относятся волоконно-оптические и экранированные кабели, а также различные категории линий типа «витая пара», поэтому многие протоколы для кабельных линий не предоставляют услуги по надежной доставке.

    Управление потоком. Узлы на каждой стороне линии связи обладают буферами для хранения кадров ограниченного размера. Это порождает потенциальную проблему, так как кадры могут поступать на получающий узел быстрее, чем этот узел способен их обрабатывать. Без управления потоком буфер получателя может переполниться, а кадры будут потеряны. Аналогично транспортному уровню протокол канального уровня может обеспечить управление потоком с целью предотвращения ситуации, когда передающий узел на одной стороне линии связи заваливает пакетами принимающий узел на другой стороне линии.

    Обнаружение ошибок. Принимающий узел может неверно посчитать, что значение бита в кадре равно нулю, в то время как передавалась единица, и наоборот. Подобные битовые ошибки вызываются ослаблением сигнала и электромагнитными помехами. Поскольку нет смысла передавать дальше дейтаграмму, содержащую ошибки, многие протоколы канального уровня предоставляют услугу по обнаружению ошибок в кадре. Для этого передающий узел добавляет к кадру биты обнаружения ошибок (контрольную сумму), а получающий узел выполняет проверку контрольной суммы. Служба обнаружения ошибок очень распространена среди протоколов канального уровня. Транспортный и сетевой уровни в Интернете также предоставляют ограниченную услугу по обнаружению ошибок. На канальном уровне обнаружение ошибок сложнее и, как правило, реализуется аппаратно.

    Исправление ошибок выполняет расширенная служба обнаружения ошибок. Такая служба способна не только обнаружить ошибку в кадре, но также определить, в каком именно разряде она произошла, и таким образом исправить некоторые ошибки. Услуга по исправлению ошибок предоставляется некоторыми протоколами канального уровня (например, ATM), но, как правило, не для всего пакета, а только для его заголовка.

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

    • адресация компьютеров во всей глобальной сети (IP-адреса);
    • выбор маршрута доставки сообщений.

    Не обеспечивает надежность доставки (искажения, потери, изменение порядка следования).

    Протоколы: IP (Internet Protocol), ARP, RARP, ICMP, DHCP.

    best-effort delivery – доставка пакетов с максимально возможной скоростью, без гарантии отсутствия задержек, потерь пакетов (при переполнении буферов на маршрутизаторах).

    Сетевой уровень отвечает за передачу датаграмм между удаленными компьютерами. Важнейшим моментом здесь является определение маршрутов пересылки пакетов от источника к пункту назначения. Маршруты могут быть жестко заданы в виде таблиц и редко меняться. Кроме того, они могут задаваться в начале каждого соединения, например, терминальной сессии. Наконец, они могут быть в высокой степени динамическими, то есть вычисляемыми заново для каждого пакета с учетом текущей загруженности сети.

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

    При путешествии пакета из одной сети в другую также может возникнуть ряд проблем. Так, способ адресации, применяемый в одной сети, может отличаться от принятого в другой. Сеть может вообще отказаться принимать пакеты из-за того, что они слишком большого размера. Также могут различаться протоколы, и т. д. Именно сетевой уровень должен разрешать все эти проблемы, позволяя объединять разнородные сети. Для преобразования IP-адресов (адресов сетевого уровня) в MAC-адреса (адреса канального уровня) в сетях TCP/IP используется протоколы ARP (англ. Address Resolution Protocol — протокол разрешения адресов) и RARP (англ. Reverse Address Resolution Protocol — обратный протокол преобразования адресов).

    Протоколы маршрутизации RIP (в локальных сетях) и BGP (в магистральный сетях) работают на прикладном уровне.

    • контроль ошибок: искажения пакетов, потери, изменение порядка следования, дублирование;
    • контроль потока данных;
    • сегментирует и повторно собирает данные в один поток;
    • обеспечивает совместное использование канала различными программами (каждой присваивается число – «номер порта»)

    Протоколы: TCP, UDP.

    Обеспечивает передачу данных между любыми узлами сети с требуемым уровнем надежности. Для этого на транспортном уровне имеются средства установления соединения, нумерации, буферизации и упорядочивания пакетов. Изолирует более высокие уровни от каких-либо изменений в аппаратной технологии.

    Транспортный уровень также определяет тип сервиса, предоставляемого сеансовому уровню и, в конечном счете, пользователям сети. Наиболее популярной разновидностью транспортного соединения является защищенный от ошибок канал между двумя узлами, поставляющий сообщения или байты в том порядке, в каком они были отправлены. Однако транспортный уровень может предоставлять и другие типы сервисов, например пересылку отдельных сообщений без гарантии соблюдения порядка их доставки или одновременную отправку сообщения различным адресатам по принципу широковещания. Тип сервиса определяется при установке соединения.

    Транспортный уровень является настоящим сквозным уровнем, то есть доставляющим сообщения от источника адресату. Другими словами, программа на машине-источнике поддерживает связь с подобной программой на другой машине при помощи заголовков сообщений и управляющих сообщений. На более низких уровнях для поддержки этого соединения устанавливаются соединения между всеми соседними машинами, через которые проходит маршрут сообщений.

    Основная функция транспортного уровня — принять данные от сеансового уровня, разбить их при необходимости на небольшие части, называемые сегментами, передать их сетевому уровню и гарантировать, что эти части в правильном виде прибудут по назначению.

    • установление сеанcа;
    • поддержка/управление сеансом;
    • разрыв сеанса;
    • синхронизация передачи данных (можно помещать контрольные точки в поток данных и возвращаться назад к определенной точке).

    Отвечает за поддержание сеанса связи, позволяя приложениям взаимодействовать между собой длительное время. Уровень управляет созданием/завершением сеанса, обменом информацией, синхронизацией задач, определением права на передачу данных и поддержанием сеанса в периоды неактивности приложений. Синхронизация передачи обеспечивается помещением в поток данных контрольных точек, начиная с которых возобновляется процесс при нарушении взаимодействия.

    • преобразование форматов данных;
    • кодирование/декодирование.

    Примеры преобразования данных: форматирование, сжатие, перевод, кодирование, шифрование.

    Отвечает за преобразование протоколов и кодирование/декодирование данных. Запросы приложений, полученные с уровня приложений, преобразует в формат для передачи по сети, а полученные из сети данные преобразует в формат, понятный приложениям. На этом уровне может осуществляться сжатие/распаковка или кодирование/декодирование данных, а также перенаправление запросов другому сетевому ресурсу, если они не могут быть обработаны локально. В отличие от более низких уровней, задача которых — достоверная передача битов и байтов, уровень представления занимается по большей части синтаксисом и семантикой передаваемой информации. Чтобы было возможно общение компьютеров с различными представлениями данных, необходимо преобразовывать форматы данных друг в друга, передавая их по сети в неком стандартизированном виде. Уровень представления занимается этими преобразованиями, предоставляя возможность определения и изменения структур данных более высокого уровня (например, записей баз данных).

    Обеспечивает взаимодействие сети и пользователя. Протоколы этого уровня определяют совместно используемые сетевые службы, например, WWW, электронную почту, сетеваую печать, пересылку файлов через сеть. Протоколы: HTTP, SMTP, POP3, IMAP, FTP. Обеспечивает взаимодействие сети и пользователя. Уровень разрешает приложениям пользователя иметь доступ к сетевым службам, таким как обработчик запросов к базам данных, доступ к файлам, пересылке электронной почты. Также отвечает за передачу служебной информации, предоставляет приложениям информацию об ошибках и формирует запросы к уровню представления. Пример: HTTP, POP3, SMTP. Содержит набор популярных протоколов, необходимых пользователям. Одним из наиболее распространенных является протокол передачи гипертекста HTTP (HyperText Transfer Protocol), который составляет основу технологии Всемирной Паутины. Когда браузер запрашивает веб-страницу, он передает ее имя (адрес) и рассчитывает на то, что сервер будет использовать HTTP. Сервер в ответ отсылает страницу. Другие прикладные протоколы используются для передачи файлов, электронной почты, сетевых рассылок. На этом уровне передаваемые данные называются сообщениями.

    Общие замечания относительно OSI ISO
    • Избыточность и низкая функциональность верхних уровней.
    • Учет в стандартах всех теоретически возможных ситуаций.
    • Сложность спецификаций для реализации.
    • Очень высокие требования к ресурсам сетевых компьютеров.

    Сегодня это референтная (ссылочная) модель.

    Хотя поддержка этого стека на правительственном уровне (США, Германия, Россия,…) продолжается, это маргинальное течение в современных сетевых технологиях.

    Эталонная модель TCP/IP

    Эталонные модели OSI и TCP

    Согласно терминологии TCP/IP элементы сетевого уровня называются подсетями (subnetworks). Идеология TCP/IP допускает, чтобы в качестве «подсетей» выступали реальные сети с их собственными стеками протоколов, узлами, шлюзами и т. п.

    Реализация протоколов TCP/IP оказалась наиболее удачной в версиях BSD4.2 и BSD4.3 операционной системы UNIX. Эта реализация является эталоном для всех последующих.

    Рассмотрим теперь эталонную модель, использовавшуюся в компьютерной сети ARPANET, которая является бабушкой нынешних сетей, а также в ее наследнице, всемирной сети Интернет.

    ARPANET была исследовательской сетью, финансируемой Министерством обороны США. В конце концов она объединила сотни университетов и правительственных зданий при помощи выделенных телефонных линий. Когда впоследствии появились спутниковые сети и радиосети, возникли большие проблемы при объединении с ними других сетей с помощью имеющихся протоколов. Понадобилась новая эталонная архитектура. Таким образом, возможность объединять различные сети в единое целое являлась одной из главных целей с самого начала. Позднее эта архитектура получила название эталонной модели TCP/IP в соответствии со своими двумя основными протоколами.

    Поскольку Министерство обороны беспокоилось, что ценные хосты, маршрутизаторы и межсетевые шлюзы могут быть мгновенно уничтожены, другая важная задача состояла в том, чтобы добиться способности сети сохранять работоспособность при возможных потерях подсетевого оборудования, так, чтобы при этом связь не прерывалась. Другими словами, Министерство обороны требовало, чтобы соединение не прерывалось, пока функционируют приемная и передающая машины, даже если некоторые промежуточные машины или линии связи внезапно вышли из строя. Кроме того, от архитектуры нужна была определенная гибкость, поскольку предполагалось использовать приложения с различными требованиями, от переноса файлов до передачи речи в реальном времени.

    Стеки протоколов

    Стеки протоколов

    Какие протоколы есть, где участвуют, какие функции нижележащих протоколов используют и какие функции предоставляют вышележащим:

    IP — реализует обмен информации дейтаграммами (IP-пакетами), для адресации узлов сети используется адрес длиной 4 байта; обеспечивает в случае необходимости фрагментацию IP-сегментов; не гарантирует правильность доставки IP-сегментов адресату и, вообще, саму доставку; не имеет средств управления интенсивностью передачи IP-сегментов посылающей стороной (flow control); не гарантирует правильную последовательность IP-сегментов на принимающей стороне.

    Пакеты сетевого протокола IP могут содержать код, указывающий, какой именно протокол следующего уровня нужно использовать, чтобы извлечь данные из пакета. Это число — уникальный IP-номер протокола. ICMP и IGMP имеют номера, соответственно, 1 и 2. Как система узнает, кому отдать пришедший пакет выше? Ведь на верхнем уровне может быть несколько протоколов. На межсетевом уровне эту проблему решает IP-код верхнего протокола, на транспортном – номер порта.

    UDP (IP идентификатор 17) (служба ненадежной, но быстрой, передачи) – протокол передачи датаграмм без установления соединения. Также его называют протоколом «ненадёжной» передачи, в смысле невозможности удостовериться в доставке сообщения адресату, а также возможного перемешивания пакетов. Однако UDP-датаграммы имеют поле контрольная сумма сообщения, что гарантирует правильность доставки сообщения, в случае, если оно дошло до адресата.

    TCP (IP идентификатор 6) (служба надежной передачи данных, устанавливающей логическое соединение) – «гарантированный» транспортный механизм с предварительным установлением соединения, предоставляющий приложению надёжный поток данных, дающий уверенность в безошибочности получаемых данных, перезапрашивающий данные в случае потери и устраняющий дублирование данных. TCP позволяет регулировать нагрузку на сеть, а также уменьшать время ожидания данных при передаче на большие расстояния. Более того, TCP гарантирует, что полученные данные были отправлены точно в такой же последовательности.

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

    HTTP – протокол TCP-порт 80 или 8080.

    Важнейшим направлением стандартизации в области вычислительных сетей является стандартизация коммуникационных протоколов. В настоящее время в сетях используется большое количество стеков коммуникационных протоколов. Наиболее популярны следующие стеки: TCP/IP, IPX/SPX, NetBIOS/SM, DECnet, SNA, OSI.

    Все эти стеки, кроме SNA на нижних уровнях — физическом и канальном, — используют одни и те же хорошо стандартизованные протоколы Ethernet, Token Ring, FDDI и ряд других, которые позволяют задействовать во всех сетях одну и ту же аппаратуру. Зато на верхних уровнях все стеки работают по своим протоколам. Эти протоколы часто не соответствуют рекомендуемому моделью OSI разбиению на уровни. В частности, функции сеансового и представительного уровня, как правило, объединены с прикладным уровнем. Такое несоответствие связано с тем, что модель OSI появилась как результат обобщения уже существующих и реально используемых стеков, а не наоборот.

    Приведены основные используемые в сетях Windows 2000 стеки протоколов. Для функционирования Windows 2000 достаточно стека TCP/ IP — стандарта передачи в сети Интернет. Поддерживаются также стек IPX/SPX — стек маршрутизируемых протоколов, появившийся в сетях NetWare, Microsoft — версия которого называется NWLink, а также NetBIOS/SMB — стек небольших и быстрых, но немаршрутизируемых протоколов.

    Принципы работы служб прикладного уровня

    Сетевая служба – это набор функций, которые уровень выполняет для вышележащего уровня (например, коррекция ошибок).

    Набор свойств и функций, которыми обладает определенный сетевой уровень, называется сетевой службой.

    Каждый сетевой уровень запрашивает определенную сетевую службу от нижележащего уровня. Протокол уровня определяет структуру данных и формат пакета для выполнения запрашиваемой сетевой службы.

    Номер порта – это целое число, которое используется для идентификации процесса, выполняющегося на данном компьютере.

    Cетевой адрес процесса – это пара «IP адрес: номер порта» (например, 127.0.0.1: 80).

    От 1 до 1023 – хорошо известные номера портов, от 1023 до 65 535 – другие.

    По сетевому номеру сообщения, полученного по сети, ОС узнает какому процессу его передать.

    Cетевое взаимодействие процессов

    Процесс обращается к службам транспортного уровня: TCP и UDP.

    Клиентская сторона приложения (службы).

    Серверная сторона приложения (службы).

    Клиенты и серверы – программы, т.е. процессы.

    На одном компьютере могут быть запущено несколько клиентов или несколько серверных процессов.

    Клиентская программа формирует запрос, посылает его на сервер, сервер обрабатывает и возвращает ответ.

    Примеры служб и протоколов. WWW (HTTP, 80), E-mail (SMTP, 25; POP3, 110; IMAP, 143), DNS (DNS, 53), FTP (FTP, 21,20), Telnet (Telnet, 23); SSH (SSH, 22), синхронизация часов (NTP, 123), передача мультимедиа (RTSP, 554), совместный доступ к файлам (SMB, 445 или NFS, 2049), DNS (Domain Name System), NTP (Network Time Protocol), RTSP (потоковый протокол реального времени (Real Time Streaming Protocol)), SMB (server message block) (см. Samba), NFS (network file system).

    Прикладной уровень

    Службы разрешения имен

    • Файл hosts.txt – файл статического сопоставления имен компьютеров и их ip-адресов.
    • Служба разрешения имен NetBIOS и ее реализация в Windows – WINS (Windows Internet Naming Service).
      • Файл lmhosts – файл статического сопоставления NetBIOS-имен и ip-адресов.

      Файлы hosts и lmhosts находятся в C:\WINDOWS\system32\drivers\etc\

      Доменные имена компьютеров

      Каждый компьютер в Интернете имеет свой IP-адрес. Сейчас распространены IP-адреса версии 4. Они представляют собой 4 числа, каждое из которых от 0 до 255. Такой адрес удобен при маршрутизации, так как определяет месторасположение компьютера в сети Интернет, однако, такие числа совсем неудобны для восприятия человеком. Более того, если, например, ваш e-mail: sasha007@207.176.39.176 и ваша почтовая служба решила сменить сервер, то вместе с ним изменится и e-mail. Гораздо лучше, когда компьютер имеет мнемоническое имя, например, mail.ru, sasha007@mail.ru. Существует файл hosts (и в UNIX, и в Windows), в котором можно прописывать адреса серверов, с которыми вы регулярно работаете.

      Доменные имена компьютеров

      DNS — иерархическая структура имен. Существует «корень дерева» с именем «.» (точка). Так как корень един для всех доменов, то точка в конце имени обычно не ставится, но используется в описаниях DNS. Ниже корня лежат домены первого уровня.

      Домены верхнего уровня разделяются на две группы: родовые домены и домены государств. К родовым относятся домены com (commercial — коммерческие организации), edu (educational — учебные заведения), gov (government — федеральное правительство США), int (international — определенные международные организации), net (network — сетевые операторы связи) и org (некоммерческие организации). За каждым государством в соответствии с международным стандартом ISO 3166 закреплен домен государства. Ниже находятся домены второго уровня, например, sfedu.ru. Еще ниже — третьего (math.sfedu.ru) и т.д.
      В ноябре 2000 года ICANN было утверждено 4 новых родовых имени доменов верхнего уровня, а именно: biz (бизнес), info (информация), пате (имена людей) и pro (специали-сты, такие как доктора и адвокаты). Кроме того, по просьбе соответствующих отраслевых организаций были введены еще три специализированных имени доменов верхнего уровня: aero (аэрокосмическая промышленность), coop (кооперативы) и museum (музеи). В буду-щем появятся и другие домены верхнего уровня. Можно регистрировать домены на кириллице, вот пример работающего сайта: http://цюрих.com/. В конце 2008г. появится домен верхнего уровня .РФ. В принципе, получить домен второго уровня типа name-of-company.com несложно. Надо лишь проверить, не занято ли желаемое имя домена кем-то другим и не является ли оно чьей-нибудь торговой маркой

      Имена доменов нечувствительны к изменению регистра символов. Так, например, edu и EDU означают одно и то же. Обычно разрешается регистрация доменов длиной до 63 символов, а длина полного пути не должна превосходить 255 символов. Размер доменного имени ограничивается по административным и техническим причинам.

      Структура доменов отражает не физическое строение сети, а логическое разделение между организациями и их внутренними подразделениями. Так, если факультеты компьютерных наук и электротехники располагаются в одном здании и пользуются одной общей локальной сетью, они, тем не менее, могут иметь различные домены. И наоборот, если, скажем, факультет компьютерных наук располагается в двух различных корпусах университета с различными локальными сетями, логически все хосты обоих зданий обычно принадлежат к одному и тому же домену.

      Служба трансляции имен DNS

      Клиенты DNS – специализированные библиотеки (или программы) для работы с DNS (в Windows – служба «DNS-клиент»).

      Серверная сторона DNS – множество серверов имен, рассредоточенных по миру и осуществляющих поиск в распределенной базе данных доменных имен.

      Порт сервера – 53.

      Серверное ПО: Berkeley Internet Name Domain (BIND) (демон named), NSD (name server daemon), Windows DNS Server

      Суть системы DNS заключается в иерархической схеме имен, основанной на доменах, и распределенной базе данных, реализующей эту схему имен. В первую очередь эта система используется для преобразования имен хостов и пунктов назначения электронной почты в IР-адреса, но также может использоваться и в других целях.

      В общих чертах система DNS применяется следующим образом. Для преобразования имени в IР-адрес прикладная программа обращается к библиотечной процедуре, называющейся распознавателем, передавая ей имя в качестве параметра. Распознаватель посылает UDP-пакет локальному DNS-серверу, который ищет имя в базе данных и возвращает соответствующий IР-адрес распознавателю, который, в свою очередь, передает этот адрес вызвавшей его прикладной программе. Имея IР-адрес, программа может установить TCP-соединение с адресатом или послать ему UDP-пакеты.

      Система DNS не только отыскивает IP-адрес по заданному имени хоста, но способна выполнять и обратную операцию, т.е. по IP-адресу определять имя хоста в сети. Многие веб- и FTP-серверы в сети Internet ограничивают доступ на основе домена, к которому принадлежит обратившийся к ним клиент. Получив от клиента запрос на установку соединения, сервер передает IP-адрес клиента DNS-серверу как обратный DNS-запрос. Если клиентская зона DNS настроена правильно, то на запрос будет возвращено имя клиентского хоста, на основе которого затем принимается решение о том, допустить данного клиента на сервер или нет.

      Дополнительные функции DNS-сервера
      1. Поддержка псевдонимов серверов. Пример: mmcs.sfedu.ru, web.mmcs.sfedu.ru и web.mmcs.rsu.ru имеют один и тот же ip-адрес
      2. Поддержка почтового сервера домена.
      3. Распределение нагрузки между серверами.
      4. Кэширование (авторитетная и неавторитетная информация).
      5. Поддержка почтового сервера домена. Можно узнать ip-адрес почтового сервера в домене (используется при пересылке почты).
      6. Распределение загрузки между серверами. Одно доменное имя соответствует нескольким серверам, следовательно, по запросу служба может вернуть несколько IP–адресов. Наример, www.microsoft.com обслуживает несколько серверов. При этом первый по списку сервер меняется от запроса к запросу. Системы обычно берут первый IP-адрес. Загрузка происходит одновременно (то к одному серверу – то к другому), но мы, как пользователи, этого не замечаем.

      Корневые серверы DNS — это серверы DNS, содержащие информацию о доменах верхнего уровня (edu, org, com, ru, …), конкретнее — указатели на серверы DNS, поддерживающие работу каждого из этих доменов.

      Authoritative DNS-server — сервер, отвечающий за какую-либо зону.

      Корневые серверы DNS обозначаются латинскими буквами от «A» до «М». Их всего 13 штук (+ куча зеркал). Они управляются различными организациями, действующими по согласованию с ICANN. Количество серверов ограничено в связи с максимальным объёмом UDP-пакета (большее количество серверов потребовало бы перехода на TCP-протокол для получения ответа, что существенно увеличит нагрузку).

      У многих корневых серверов DNS существуют зеркала. В частности, российское зеркало сервера F расположено в РосНИИРОС. IP-адреса корневых DNS-серверов можно получить командой «dig. NS» (dig точка NS; точка – корневой домен).

      The DNS Backbone DDoS Attacks have been several significant Internet events in which distributed denial of service attacks (DDoS) have targeted one or more of the thirteen DNS root servers. These attacks are extremely significant, as the root nameservers function as the Internet backbone, translating text-based Internet hostnames into IP addresses. As the nameservers provide this service for DNS lookups worldwide, attacks against the root nameservers are attempts to disable the Internet itself, rather than specific websites.

      The first attack occurred on October 21, 2002, and lasted for approximately one hour. Of the thirteen servers, nine were disabled but the remaining four were able to cope. This was the second near-major failure of the root nameservers; the first large malfunction of them caused the failure of seven machines in July 1997, due to a technical problem. A second attack occurred on February 6, 2007. The attack began at 10:30 UTC, and lasted about five hours. Although none of the servers crashed, two of the root servers reportedly «suffered badly», while others saw «heavy traffic». The botnet responsible for the attack has reportedly been traced to the Asia-Pacific region. [2] There was some speculation in the press that the attack originated from South Korea. [3] On February 8, 2007 it was announced by Network World that «If the United States found itself under a major cyberattack aimed at undermining the nation’s critical information infrastructure, the Department of Defense is prepared, based on the authority of the president, to launch a cyber counterattack or an actual bombing of an attack source.»[4]

      Принципы работы DNS

      Принципы работы DNS

      Рассмотрим схему подачи запроса серверу. Студент Стэнфордского университета с университетского компьютера пытается зайти на сайт воскресной школы мехмата sunschool.math.sfedu.ru. Чтобы определить IP-адрес компьютера sunschool.math.sfedu.ru, браузер студента вызывает DNS-клиент (resolver) – функцию API операционной системы. Она, используя IP-адрес локального DNS-сервера из настроек сети на компьютере студента, посылает запрос в виде UDP-пакета DNS-серверу. Пусть сервер будет atalante.stanford.edu.

      Предположим, что локальный сервер Стэнфордского университета имен не знает IP-адреса sunschool.math.sfedu.ru. Тогда он посылает запрос одному из корневых серверов, адреса которых содержатся в его базе данных, пусть это будет f.root-servers.net. Таким образом получается рекурсивный запрос: DNS-клиент студента обращается к локальному DNS-серверу, а тот к корневому.

      Маловероятно, что корневой сервер знает адрес хоста sunschool.math.sfedu.ru. Скорее всего он даже не знает адреса сервера sfedu.ru, однако он должен знать все свои дочерние домены – домены верхнего уровня. Но продолжать рекурсию он не будет. Дело в том, что корневые домены сильно загружены запросами, поэтому сконфигирированы так, что возвращают список DNS-серверов, которые должны больше знать о sunschool.math.sfedu.ru – это DNS-серверы домена ru. Получив список DNS-серверов, локальный сервер Стэнфордского университета направляет запрос одному из серверов списка (обычно первому), например, ns.ripn.net. Тот тоже загружен и возвращает адреса DNS-серверов дочерней зоны sfedu.ru. Последние два запроса называются итеративными (от слова «итерация»). Затем локальный сервер Станфордского университета обращается к первому в списке серверу домена sfedu.ru. Пусть это будет ns.sfedu.ru. В данном примере оказалось, что он тоже не знает IP-адреса sunschool.math.sfedu.ru. DNS-сервер нашего университета не так загружен, как корневые серверы или серверы доменов верхнего уровня, поэтому его сконфигурировали выполнять рекурсивные запросы. Он обращается к серверу домена math.sfedu.ru – это ns.math.sfedu.ru, получает искомый IP-адрес и возвращает его в ответе локальному серверу Стэнфордского университета, который, в свою очередь, сообщает его компьютеру студента.

      Когда записи ресурсов попадают на сервер имен Стэнфордского университета, они помещаются в кэш на случай, если они понадобятся еще раз. Однако, информация в кэше не является авторитетной, так как изменения в домене sfedu.ru не будут автоматически распространяться на все кэши, в которых может храниться копия этой информации. По этой причине записи кэша обычно долго не живут. В каждой записи ресурса присутствует поле Time_to_live. Оно и сообщает удаленным серверам, насколько долго следует хранить эту запись в кэше.

      Набор DNS-серверов в ответе на запрос все время один и тот же, однако, их последовательность в списке меняется от запроса к запросу, так как программы обычно берут первое имя из списка, то они обращаются к разным серверам. Таким образом нагрузка равномерно распределяется между DNS-серверами списка.

      Отметим также, что использование файла hosts лежит в основе многих «ускорителей Интернета» — такие программы просто записывают адреса серверов, к которым вы обращаетесь, в файл hosts и при следующем обращении берут данные из него, не тратя время на запрос к DNS-серверу.

      Структура DNS-сообщения

      Запросы и ответы имеют один формат и состоят из:

      • заголовка, включающего в себя идентификатор, размер сообщения, количество вопросов/ответов и т.д. (12 байтов);
      • секции вопросов (название, тип);
      • секции ответов (набор RR (resource record) — записей из БД DNS);
      • секции полномочности, которая содержит ссылки на полномочные сервера («Не знаю, но знаю у кого спросить»);
      • дополнительной информации (IP-адреса тех, у кого можно еще спросить).

      Это часть описания DNS-протокола.

      Результат, возвращаемый командой dig:

      ;; ->>HEADER
      

      dig @f.root-servers.net sunschool.math.sfedu.ru IN A — спрашиваем у одного из корневых серверов адрес воскресной школы мехмата. Сервер отсылает нас к DNS-серверам зоны ru. Секции ответов нет – она пустая, т.е. корневой сервер не знает адреса воскресной школы. Зато он знает у кого можно спросить еще. В дополнении указаны IP-адреса серверов, у которых можно спросить.

      Сервер DNS для Linux

      BIND (Berkeley Internet Name Domain) — программный пакет системы DNS для UNIX систем. Функции сервера DNS в этом пакете реализует программа named (от «name daemon»). На большинстве корневых серверов стоит BIND.

      Конфигурационные файлы:
      /etc/host.conf – определяются методы и порядок преобразования имен ОС Linux;
      /etc/named.conf – опции программы named и список файлов, в которых находятся описания зон.

      Пример файла /etc/host.conf
      1 order hosts,bind 2 multi on

      В первой строке указывается порядок преобразования имен хостов. Здесь операционной системе Linux указывается, что в первую очередь она должна обращаться к файлу /etc/hosts и искать хост там, а затем попытаться преобразовать имя с помощью системы DNS (bind), если не удалось этого сделать с помощью /etc/hosts.

      Пример файла /etc/named.conf для кэширующего DNS-сервера
      1 options < 2 directory "/var/named; 3 >; 4 5 zone "." < 6 type hint; 7 file "root.cache"; 8 9 >; 10 11 12 zone "localhost" < 13 type master; 14 file "pri/localhost"; 15 >; 16 17 zone."0.0.127.in-addr.arpa" < 18 type master; 19 file "pri/127.0.0"; 20 >;

      Дополнения к файлу /etc/named.conf с описанием зоны:

      1 zone smallorg.org < 2 type master 3 file "pri/smallorg.org"; 4 >; 5 6 zone 0.163.192 in -addr.arpa < 7 type master; 8 file "pri/192.168.0"; 9 >;

      Типы записей в базе данных DNS-сервера

      Типы записей в базе данных DNS-сервера

      DNS-сервер, отвечающий за имена хостов в своей зоне, должен хранить информацию о хостах в базе данных и выдавать ее по запросу с удаленных компьютеров. База данных DNS представляет собой текстовый файл, состоящий из исходных записей RR. Эти записи описывают компьютеры и их функции в локальной зоне. Для организации обмена информацией с удаленными серверами DNS на сервере Linux должно быть запущено программное обеспечение сервера DNS (обычно это программа named).

      Прежде всего в базе данных сервера DNS должна быть объявлена зона (логический узел в дереве DNS-имён), за которую данный сервер несет ответственность. Далее в ней должны быть объявлены все хост-компьютеры, имеющиеся в зоне. И, наконец, в базе данных можно объявлять специальную информацию, касающуюся зоны (например, о серверах электронной почты и DNS-серверах). Формат записи базы данных был разработан таким образом, чтобы DNS-сервер мог почерпнуть из нее любую информацию, нужную для его работы. В таблице приведены основные типы исходных записей, которые могут присутствовать в базе данных DNS. База данных DNS в последнее время стала темой для дискуссий среди исследователей, так как многие хотят дополнить ее новыми возможностями и наряду с этим повысить уровень безопасности. В настоящее время в базу данных DNS постоянно вносятся новые типы записей. В таблице отражены лишь основные типы записей, которые необходимы для открытия и ведения новой зоны в базе данных DNS.

      Зона и серверы имен

      Файл описания зоны, содержит совокупность записей о ресурсах и доменах следующего (более низкого) уровня, расположенных в текущем домене. В каждой зоне должен быть как минимум один сервер имен. Каждому серверу имен известен адрес хотя бы одного родительского сервера имен.

      Консорциум Всемирной паутины

      С 1994 года основную работу по развитию Всемирной паутины взял на себя Консорциум Всемирной паутины (англ. World Wide Web Consortium, W3C), основанный и до сих пор возглавляемый Тимом Бернерсом-Ли. Данный Консорциум — организация, разрабатывающая и внедряющая технологические стандарты для Интернета и Всемирной паутины. Миссия W3C: «Полностью раскрыть потенциал Всемирной паутины, путём создания протоколов и принципов, гарантирующих долгосрочное развитие Сети». Две другие важнейшие задачи Консорциума — обеспечить полную «интернационализацию Сети» и сделать Сеть доступной для людей с ограниченными возможностями.

      W3C разрабатывает для Интернета единые принципы и стандарты (называемые «Рекомендациями», англ. W3C Recommendations), которые затем внедряются производителями программ и оборудования. Таким образом достигается совместимость между программными продуктами и аппаратурой различных компаний, что делает Всемирную сеть более совершенной, универсальной и удобной. Все Рекомендации Консорциума Всемирной паутины открыты, то есть не защищены патентами и могут внедряться любым человеком без всяких финансовых отчислений консорциуму.

      Клиенты WWW

      Веб-браузеры

      Веб-браузер (Web browser) 3 это программа для запросов и отображения вебстраниц, и перехода от одной страницы к другой.

      URL (Uniform Resourse Locator) — универсальный адрес ресурса.

      Историчская справка. Развитие веб-браузеров.

      Изначальное предложение, создать паутину из связанных друг с другом документов пришло от физика центра CERN Тима Бернерс-Ли (Tim Berners-Lee) в марте 1989 года. Первый (текстовый) прототип заработал спустя 18 месяцев. В декабре 1991 году на конференции Hypertext'91 в Сан-Антонио в штате Техас была произведена публичная демонстрация.

      Эта демонстрация, сопровождаемая широкой рекламой, привлекла внимание других ученых. Марк Андрессен (Marc Andreessen) в университете Иллинойса начал разработку первого графического браузера, Mosaic. Программа увидела свет в феврале 1993 года и стала популярной.

      В 1994 году CERN и Массачусетский технологический институт (M.I.T., Massachusetts Institute of Technologies) подписали соглашение об основании WWW-консорциума (World Wide Web Consortium, иногда применяется сокращение W3C) — организации, цель которой заключалась в дальнейшем развитии приложения Web, стандартизации протоколов и поощрении взаимодействия между отдельными сайтами. Бернерс-Ли стал директором консорциума. Хотя о Всемирной паутине уже написано очень много книг, лучшее место, где вы можете получить самую свежую информацию о ней, это сама Всемирная паутина. Домашнюю страницу консорциума можно найти по адресу http://www.w3.org. На этой странице заинтересованный читатель найдет ссылки на другие страницы, содержащие информацию обо всех документах консорциума и о его деятельности.

      В апреле 1994 года Марк Андрессен и Джим Кларк, бывший профессор Стенфордского университета, образовали корпорацию Netscape Communication. В состав корпорации вошли многие ученые, вместе с Андрессеном занимавшиеся созданием браузера Mosaic, и в октябре 1994 года вышла в свет бета-версия продукта Netscape Navigator 1.0. В последующие годы компания приложила множество усилий для развития нового браузера и других технологий: web-серверов, коммерческих серверов, почтовых серверов, серверов новостей, прокси-серверов, программ чтения электронной почты и др. Netscape Communication по праву можно считать одной из самых прогрессивных и успешных Интернет-компаний середины 1990-х, а в августе 1995 года громкий публичный успех пришел к браузеру Netscape.

      Компания Microsoft, изначально не проявлявшая значительной активности по продвижению своих интересов в Интернет, выпустила 1-ю версию браузера Microsoft Internet Explorer в августе 1995 года. Продукт не отличался изяществом и скоростью [источник?] , однако компания вложила значительные инвестиции в его развитие, и к 1997 году Microsoft и Netscape шли бок о бок в «браузерной гонке».

      11 июня 1997 года Netscape выпустила версию 4.0 своего браузера, а 30 сентября вышла в свет версия 4.0 Microsoft Internet Explorer. В то время еще не сложилось устоявшегося мнения о том, какой из браузеров лучше, а компания Microsoft, обладавшая монополией на свою операционную систему Windows, набирала все большую коммерческую мощь.

      В 1997 году компания Netscape допустила ряд решающих просчетов: не была осознана важность создания портала на основе web-сайта компании, кроме того, было принято ошибочное решение о полном переходе браузера на Java-технологию. В конечном счете, 1998 год ознаменовался для Netscape Communication снижением ее доли на рынке браузеров и других продуктов, в конце года она была приобретена компанией America Online, а Марк Андрессен и большая часть его команды покинули свое бывшее детище.

      Acid3 — тест поддержки браузером веб-стандартов. Он осуществляет проверку 100 вероятно уязвимых мест в HTTP, HTML, CSS, ECMAScript, SVG и XML, а также проверяет работу с DOM. Намеренно выбирались такие тесты, которые не проходила сборка хотя бы одного из браузеров того времени (последние 16 тестов — Firefox или Safari).

      Другие клиенты
      • Мобильный телефон может получить доступ к ресурсам веб-сервера.
      • Другие интеллектуальные устройства или бытовая техника.
      • Специальное программное обеспечение может самостоятельно обращаться к веб-серверам для получения обновлений или другой информации.

      Веб-серверы

      Веб-сервер — это программа, принимающая HTTP-запросы от клиентов и выдающая им HTTP-ответы, обычно вместе с HTML-страницей, изображениями, файлами, медиа-потоком или другими данными.

      Дополнительные функции веб-серверов
      • ведение журнала обращений пользователей к ресурсам;
      • аутентификация пользователей;
      • поддержка динамически генерируемых страниц;
      • поддержка HTTPS для защищённых соединений с клиентами.

      Стандартный порт: 80/TCP (8080).

      Популярные веб-серверы
      • Apache;
      • Microsoft Internet Information Services (IIS);
      • nginx;
      • lighttpd
      Установка и настройка Apache

      Файл apache\conf\httpd.conf
      ServerName localhost
      AddDefaultCharset windows-1251
      Listen 80
      DirectoryIndex index.php index.htm index.html

      HomServ — дистрибутив для Microsoft Windows, включающий Apache, PHP, MySQL, phpMyAdmin.
      Denwer — дистрибутив для Microsoft Windows, включающий Apache.
      Apache после установки создает каталог, где хранятся странички.

      Протокол HTTP (HyperText Transfer Protocol)

      1. Браузер определяет IP-адрес сервера, по известному имени из URL.
      2. Устанавливает TCP-соединение с сервером.
      3. Отправляет текстовый запрос:

      GET /index.html HTTP/1.1 User-Agent: Opera/9.24 (Windows NT 5.1; U; ru) Host: www.math.rsu.ru Connection: Keep-Alive

      Рассмотрим запрос поробнее.
      GET – команда веб-серверу (тип запроса). Такие команды называются «методами».
      /index.html – URI (Uniform Resource Identifier) – имя ресурса.
      HTTP/1.1 – протокол HTTP версии 1.1.
      Host: www.math.rsu.ru.
      Connection: Keep-Alive – не разрывать TCP-соединение (еще есть close).

      Протокол HTTP версии 1.0 поддерживал только непостоянные соединения. Для веб-страницы, состоящей, например, из текста и 10 картинок в случае непостоянного соединения приходится 11 раз устанавливать и разрывать TCP-соединения, а это долгая процедура (см. лекцию про TCP, транспортный уровень). В HTTP 1.1 добавили возможность устанавливать постоянные соединения, да еще с конвейеризацией. В соединениях без конвейеризации клиент посылает запрос серверу после того как закончит прием текущего объекта. В соединениях с конвейеризацией клиент запрашивает объекты (например, картинки) сразу после обнаружения ссылки на них в HTML-документе, не дожидаясь окончания приема текста.

      При помощи сниффера (например, Wireshark) можно получить данные реальных запросов:

      Приведем пример запроса браузера:

      GET /index.html HTTP/1.1 // обязательная строка User-Agent: Opera/9.24 (Windows NT 5.1; U; ru) Host: www.math.rsu.ru // обязательная строка Accept: text/html, application/xml;q=0.9, application/xhtml+xml, image/png, image/jpeg, image/gif, image/x-xbitmap, */*;q=0.1 Accept-Language: ru,en;q=0.9 Accept-Charset: iso-8859-1, utf-8, utf-16, *;q=0.1 Connection: Keep-Alive

      Ответ сервера мехмата:

      HTTP/1.1 200 OK Date: Mon, 07 Jul 2008 15:10:06 GMT Server: Apache/1.3.37 (Unix) mod_perl/1.29 PHP/4.4.6 mod_ssl/2.8.28 OpenSSL/0.9.8e rus/PL30.22 Last-Modified: Tue, 17 Jun 2008 12:22:22 GMT ETag: "73619c-1d0d-4857ac7e" Accept-Ranges: bytes Content-Length: 7437 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html   Учебно-научный центр "Механика. Математика" и т.д.

      HTTP-ответ сервера

      Сервер формирует ответ, состоящий из заголовка и тела.

      '''HTTP/1.1 200 OK Server: Apache/1.3.37 (Unix) mod_perl/1.29 PHP/4.4.6 Last-Modified: Tue, 17 Jun 2008 12:22:22 GMT Content-Length: 7437 Keep-Alive: timeout=15, max=100 Connection: Keep-Alive Content-Type: text/html'''  Учебно-научный центр "Механика. Математика".

      Браузер получает ответ, выделяет из него тело и отображает соответствующий документ.

      Коды ошибок, возвращаемых веб-сервером.

      200 OK: Запрос успешно обработан, объект получен и включен в ответ. 301 Moved Permanently: Объект был перемещен; новый URL-адрес указан в строке ответа Location:. Программа клиента автоматически выполнит запрос по новому адресу. 400 Bad Request: Общая ошибка, вызванная невозможностью интерпретации запроса сервером. 404 Not Found: Запрашиваемый документ не найден на сервере. 505 HTTP Version Not Supported: Указанная в запросе версия HTTP не поддерживается сервером.

      Если в файле используется картинки, то для каждой будет сформирован дополнительный запрос.

      Рендеринг – процесс отображения страницы.

      Передача данных от клиента на сервер по протоколу HTTP

      Проблема – передача данных от клиента к серверу. Протокол HTTP изначально позволял только получать клиенту данные от сервера. Если добавить возможность отправки данных на веб-сервер, как тогда серверу их обрабатывать?

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

      С этим столкнулись в самом начале развития WWW. Например, для отображения конфиденциальной информации клиент должен послать логин и пароль (это было реализовано средствами веб-сервера); другой пример — поисковой системе, работающей на сервере, нужны данные от клиента (строка запроса). Когда осознали необходимость этого, то поняли, что на сервер все функции повесить нельзя – нужно что-то поручать сторонним программам и придумали CGI – стандарт общения сервера с программами.

      CGI-приложения

      CGI (Common Gateway Interface) — стандарт обмена данными между прикладной программой, выполняемой по запросу пользователя, и HTTP-сервером, который данную программу запускает.

      Данные передаются программе:

      • через переменные окружения;
      • на стандартный вход.

      Программа передает данные серверу через стандартный выход. Формат такой же как у HTTP-ответа.

      Common Gateway Interface — «общий интерфейс шлюза». Здесь Gateway (шлюз) — программа, которая работает по такому интерфейсу совместно с веб-сервером (многие предпочитают названия «скрипт» (сценарий) или «CGI-программа»).

      Задача веб-сервера – отвечать на запросы клиентов. Сервер анализирует каждый запрос. Если клиенту нужен html-файл (не обязательно html), то сервер просто возвращает содержимое этого файла. А если клиент указывает в запросе на выполняемую программу и посылает в добавок аргументы для этой программы, сервер должен запустить эту программу с указанными аргументами и послать пользователю результат ее выполнения.

      CGI определяет стандарты такого запуска программ на сервере: как информация из запроса и данные о сервере передаются программе (что через командную строку, что через переменные окружения) и как программа может возвратить дополнительную информацию о результате (например, его тип) в виде заголовков.

      Сам интерфейс разработан таким образом, чтобы можно было использовать любой язык программирования, который может работать со стандартными устройствами ввода/вывода. Такими возможностями обладают даже скрипты для встроенных командных интерпретаторов операционных систем, поэтому в тех случаях, когда нет нужды в сложной функциональности, могут использоваться даже такие простые командные скрипты.

      Все скрипты, как правило, помещают в каталог cgi-bin сервера, но это необязательно: скрипт может располагаться где угодно, но при этом большинство веб-серверов требуют специальной настройки.

      В веб-сервере Apache, например, такая настройка может производится при помощи общего файла настроек httpd.conf или с помощью файла.htaccess в том каталоге, где содержится этот скрипт. Также Apache позволяет запускать все скрипты, имеющие расширение.cgi.

      Методы HTTP-запросов

      GET – запрашивает содержимое указанного ресурса. В случае наличия у ресурса параметров, они передаются в URI: http://www.example.net/resource?param1=value1¶m2=value2 POST – передает пользовательские данные (например, из HTML-формы) заданному ресурсу HEAD – запрашивает заголовок указанного ресурса PUT – загружает указанный ресурс на сервер DELETE – удаляет указанный ресурс

      Методы

      Возвращает методы HTTP, которые поддерживаются сервером. Этот метод может служить для определения возможностей веб-сервера.

      Запрашивает содержимое указанного ресурса. Запрашиваемый ресурс может принимать параметры (например, поисковая система может принимать в качестве параметра искомую строку). Они передаются в строке URI (например: http://www.example.net/resource? param1=value1¶m2=value2). Параметры – это и есть данные от клиента: имя и пароль, строка запроса к поисковой системе и т.п. Согласно стандарту HTTP, запросы типа GET считаются идемпотентными — многократное повторение одного и того же запроса GET должно приводить к одинаковым результатам (при условии, что сам ресурс не изменился за время между запросами). Это позволяет кэшировать ответы на запросы GET.

      Аналогичен методу GET, за исключением того, что в ответе сервера отсутствует тело. Это полезно для извлечения метаданных, заданных в заголовках ответа, без пересылки всего содержимого.

      Передаёт пользовательские данные (например, из HTML-формы) заданному ресурсу. Например, в блогах посетители обычно могут вводить свои комментарии к записям в HTML-форму, после чего они передаются серверу методом POST и он помещает их на страницу. При этом передаваемые данные (в примере с блогами — текст комментария) включаются в тело запроса. В отличие от метода GET, метод POST не считается идемпотентным, то есть многократное повторение одних и тех же запросов POST может возвращать разные результаты (например, после каждой отправки комментария будет появляться одна копия этого комментария).

      Загружает указанный ресурс на сервер.

      Удаляет указанный ресурс.

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

      Для использования вместе с прокси-серверами, которые могут динамически переключаться в туннельный режим SSL.

      В основном используются методы GET и POST.

      Метод POST

      После нажатия на кнопку «отправить» браузер посылает серверу сообщение. Приводим реальные данные, перехваченные сниффером. Запрос браузера к серверу, установленному на этом же компьютере:

      (1) POST /action.php HTTP/1.1 (2) Host: test1.ru (3) User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.8.0.11) Gecko/20070324 (Debian-1.8.0.11-2) Epiphany/2.14 (4) Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5 (5) Accept-Encoding: gzip,deflate (6) Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7 (7) Keep-Alive: 300 (8) Connection: keep-alive (9) Referer: http://test1.ru/ (10) Content-Type: application/x-www-form-urlencoded (11) Content-Length: 18 (12) (13) name=sergey&age=26

      (1) action.php — это программа на сервере, которой передаются введенные данные. По этим данным она сгенерирует html-страницу, которая затем будет отправлена сервером браузеру.

      (3) Это браузер ОС Linux Debian, установленной у клиента на виртуальной машине. Виртуальной машиной пришлось воспользоваться, так как сниффер не может перехватить запрос от браузера на локальной машине направленный к серверу на той же машине, т.е. через интерфейс 127.0.0.1.

      (10) Тип передаваемого содержимого.

      (11) Размер содержимого.

      Приведем код HTML-странички (об HTML будем говорить позже):

      Ваше имя:

      Ваш возраст:

      Передача данных CGI-приложению

      Передача данных CGI-приложению может осуществляться методами GET и POST.

      GET POST
      Как данные передаются серверу В url В теле запроса
      Как сервер передает данные программе Через переменные окружения (QUERY_STRING) Через поток стандартного ввода
      Используется для передачи небольших массивов данных больших, в частности TEXTAREA и файлов
      Кодирование и формат отправляемых данных

      По умолчанию – application/x-www-form-urlencoded Все символы не из первой половины ASCII заменяются их кодами, например, “a” на “%E0”. Пробелы – на «+», «&» – на «%26».

      multipart/form-data – используется для отправки двоичных данных и данных смешанного типа.

      Существует два типа кодирования содержания (тела) HTTP-сообщения, которые можно определить в форме:

      • application/x-www-form-urlencoded
      • multipart/form-data

      Первый тип кодирования выбирается по умолчанию и является основным способом. В URL документа можно использовать только символы набора Latin1. Это первая половина таблицы ASCII за вычетом первых 20 символов. Все остальные символы заменяются своими шестнадцатеричными эквивалентами. Кроме того, такие символы, как "+" или "&", играют роль разделителей или коннекторов. Если они встречаются в значении поля, то тоже заменяются на шестнадцатеричный эквивалент. Наиболее характерно это для работы с русским алфавитом. Поэтому скрипт, который принимает запросы, должен уметь эти символы декодировать.

      Второй тип применяется для передачи двоичной информации в теле HTTP-сообщения. Если проводить аналогии с электронной почтой, то multipart/form-data обеспечивает присоединение файла данных (attachment) к HTTP-запросу. Наиболее типичным примером является передача файла с машины пользователя на сервер:

      В данном случае HTTP-сообщение будет очень похоже на почтовое сообщение в стандарте MIME (собственно, это и есть MIME-сообщение, только передается оно по протоколу HTTP). Естественно, что для приема такого сообщения нужен скрипт, который бы смог разобрать его на части, а потом декодировать необходимую информацию.

      Сообщение типа "multipart/form-data" состоит из нескольких частей, каждая их которых представляет успешный управляющий элемент. Части отправляются обрабатывающему агенту в том порядке, в котором соответствующие управляющие элементы представлены в потоке документа. Границы частей не должны находиться в данных.

      Как и во всех составных типах MIME, каждая часть имеет необязательный заголовок "Content-Type", для которого по умолчанию устанавливается значение "text/plain". Агенты пользователей должны предоставлять заголовок "Content-Type" с параметром "charset".

      Каждая часть должна содержать:

      • заголовок "Content-Disposition", имеющий значение "form-data";
      • атрибут именования, определяющий имя соответствующего управляющего элемента. Имена управляющих элементов, изначально закодированные с использованием наборов символов, отличных от ASCII, могут кодироваться с помощью метода, описанного в [RFC2045].
      application/x-www-form-urlencoded BigText= TextTextText&pol1= m multipart/form-data ------------Gt1CO3wAR7XTbm1eE7LoA6 Content-Disposition: form-data; name="BigText " TextTextText ------------Gt1CO3wAR7XTbm1eE7LoA6 Content-Disposition: form-data; name="pol1 " m ------------Gt1CO3wAR7XTbm1eE7LoA6--

      multipart/form-data – для отправки больших объемов данных или двоичных файлов

      Пример CGI-скрипта (GET) на PascalABC
      s:=Environment.GetEnvironmentVariable('QUERY_STRING'); writeln(file,'Переменная окружения QUERY_STRING: ',s); writeln('Content-Type: text/html'); writeln(‘'); writeln('   OK   

      Введенные в форму данные успешно записаны в файл zapros_get.txt

      ')
      Пример CGI-скрипта (POST) на PascalABC
      Val(Environment.GetEnvironmentVariable('CONTENT_LENGTH'),n,err); writeln(file,'Размер: ',n); writeln(file,'Данные:'); SetLength(s,n); for i:=0 to n-1 do read(s[i]); for i:=0 to n-1 do write(f,s[i]); writeln('Content-Type: text/html'); writeln(''); writeln('   OK   

      Введенные в форму данные успешно записаны в файл zapros_post.txt

      ')
      Недостатки и альтернативы CGI

      Недостаток CGI: вызов программы – «дорогая» операция, особенно если это скрипт, который еще нужно интерпретировать (или откомпилировать).

      • встроенные в веб-сервер модули (mod_php, mod_perl в Apache);
      • Fast CGI.

      Проблема CGI-программ в том, что они должны быть перезапущены веб-сервером при каждом запросе, что приводит к понижению производительности.

      FastCGI убирает это ограничение, сохраняя процесс запущенным и передавая запросы этому постоянно запущенному процессу. Это позволяет не тратить время на запуск новых процессов.

      В то время как CGI-программы взаимодействуют с сервером через STDIN и STDOUT запущенного CGI-процесса. FastCGI-процессы используют Unix Domain Sockets или TCP/IP для связи с сервером. Благодаря этому, в отличие от обычных CGI-программами, FastCGI-программы могут быть запущены не только на этом же сервере, но и где угодно в сети. Также возможна обработка запросов несколькими FastCGI-процессами, работающими параллельно.

      Языки программирования CGI-приложений
      • PHP;
      • Perl;
      • Microsoft ASP.NET (на сервере IIS);
      • JSP (Java Server Pages);
      • Python;
      • Ruby

      Cookies

      HTTP-Cookie — служебная информация, посылаемая веб-сервером на компьютер пользователя, для сохранения браузером на локальном компьютере.

      • для отличия пользователей веб-сервером друг от друга;
      • для сохранения данных о действиях пользователя.

      Cookies были придуманы, чтобы реализовать «Корзину покупателя» — виртуальную корзину, в которую пользователь мог бы добавлять приобретенные на сайте вещи (как в супермаркете), а потом в конце расплачиваться за все.

      Еще одна цель создания cookie – организация входа (log in) на сайт. Сервер различает пользователей именно по cookie, которые посылают ему браузеры при запросе каждой страницы с сайта.

      Сторонние cookies

      Иногда веб-странички включают в себя содержимое с других сайтов, например, рекламу с сайта рекламного агентства. Чтобы загрузить этот веб-элемент браузер (вне ведома от пользователя) обращается к серверу рекламного агентства, который может установить cookie. Вот такие cookie называются сторонними. Если такие cookies включают в себя информацию о посещаемом вами сайте, то это дает рекламному агентству возможность следить за вашим перемещением в Интернете по сайтам с его рекламой и выдавать вам рекламу того, чем вы больше интересуетесь. Таким образом нарушается тайна частной жизни пользователей. В штатах устанавливать такие cookie запрещено законом.

      Механизм Cookies

      Сервер ( CGI-программа) может установить cookie в ответ на запрос браузера. Для этого в заголовок ответа он добавляет строчку Set-Cookie, например,

      Set-Cookie: sessionID=678893467800; lang= ru; domain=mydomain.com; expires=09-Nov-08 23:12:40

      Браузер соxраняет cookie и затем посылает на этот сервер в виде строки Cookie в заголовке каждого запроса, например,

      Cookie: sessionID=678893467800; lang= ru;

      Куки также может быть установлена и самим браузером через JavaScript, который поддерживается большинством современных браузеров. Браузер должен соxранять куки на период определенный для ее времени жизни и посылать куки на сервер в заголовке запроса (request header) Cookie. В запросе посылаются только те куки, которые соответствуют домену, пути и протоколу для которых куки была установлена Клиент (браузер) имеет следующие ограничения для cookies, например: всего может храниться до 300 значений cookies, каждый cookie не может превышать 4Кбайт, с одного сервера или домена может храниться до 20 значений cookie.

      Главной проблемой является изначальное недоверие пользователей к тому, что удаленные сервера без их (пользователей) ведома и согласия записывают на их собственные локальные диски какую либо информацию. Бытовали также слухи о том, что с помощью механизма cookie можно прочесть любую информацию с любого компьютера. Это неправда, к тому же современные версии браузеров позволяют контролировать прием cookie или вовсе блокировать его. Кроме того, появилось множество специальных утилит для управления приемом cookie, так называемые Cookie Managers. Другая сторона этой проблемы заключается в том, что на узлах Сети аккумулируются огромные массивы данных с персональной информацией, необходимые для коммерческих серверов. Вот здесь и появляются повышенные требования к защите от несанкционированного доступа к этим данным. Пользователи таких серверов должны быть уверены, что их имена, адреса электронной почты, телефонные номера и проч., не попадут в чужие руки. В противном случае последствия могут оказаться катастрофическими для "проштрафившихся" коммерческих серверов.

      Язык разметки гипертекста HTML

      HTML — это теговый язык разметки документов. Любой документ на языке HTML представляет собой набор элементов, причём начало и конец каждого элемента обозначается специальными пометками — тегами. Элементы могут быть пустыми, то есть не содержащими никакого текста и других данных (например, тег перевода строки
      ). В этом случае обычно не указывается закрывающий тег. Кроме того, элементы могут иметь атрибуты, определяющие какие-либо их свойства (например, размер шрифта для элемента font). Атрибуты указываются в открывающем теге.

      Историческая справка. Развитие HTML

      Язык HTML был разработан британским учёным Тимом Бернерсом-Ли приблизительно в 1991—1992 годах в стенах Европейского совета по ядерным исследованиям в Женеве (Швейцария). HTML создавался как язык для обмена научной и технической документацией, пригодный для использования людьми, не являющимися специалистами в области вёрстки. Сейчас Консорциумом Всемирной паутины (W3C) разрабатывает пятую версию языка HTML5.

      Черновой вариант спецификации языка появился в Интернете 20 ноября 2007. Параллельно ведётся работа по дальнейшему развитию HTML под названием XHTML (от англ. Extensible Hypertext Markup Language — «расширяемый язык разметки гипертекста»). Пока XHTML по своим возможностям сопоставим с HTML, однако предъявляет более строгие требования к синтаксису. XHTML, в отличие от предшественника, основан на XML.

      Вариант XHTML 1.0 был одобрен в качестве Рекомендации Консорциума Всемирной паутины (W3C) 26 января 2000 года.

      Пример 1. Простейший HTML-документ.

       Начало HTML-документа Заголовок Hello HTML // Появится в заголовке окна рядом с названием браузера  // Тело документа Этот текст будет выведен полужирным, а этот ещё и курсивом  Так оформляется гиперссылка  

      Пример 2. Страница факультета психологии животных.

        ФПЖ  

      Факультет психологии животных

      О нас

      Персонал

      Популярные курсы

      Регистр, в котором набрано имя элемента и имена атрибутов, в HTML значения не имеет (в отличие от XHTML). Элементы могут быть вложенными.

      Кроме элементов, в HTML-документах есть и сущности (англ. entities) — «специальные символы». Сущности начинаются с символа амперсанда и имеют вид &имя; или &#NNNN;, где NNNN — код символа в Юникоде в десятеричной системе счисления. Например, © — знак авторского права (©). Как правило, сущности используются для представления символов, отсутствующих в кодировке документа, или же для представления «специальных» символов: & — амперсанда (&), < — символа «меньше» (<) и >— символа «больше» (>), которые некорректно записывать «обычным» образом, из-за их особого значения в HTML.

      Каждый HTML-документ, отвечающий спецификации HTML какой-либо версии, должен начинаться со строки объявления версии HTML , которая обычно выглядит примерно так:

      Если эта строка не указана, то добиться корректного отображения документа в браузере становится труднее.

      Далее обозначается начало и конец документа тегами и соответственно. Внутри этих тегов должны находиться теги заголовка ( ) и тела ( ) документа.

      Добавим информацию на страницу факультета психологии животных из второго примера.

      Страница факультета психологии животных

      Редакторы HTML
      • Adobe Dream Weaver;
      • Microsoft Expression Web;
      • SharePoint Designer (бесплатный);
      • Web Development Studio (бесплатная);
      • Word;
      • Microsoft Front Page (поддержка прекращена).

      Историчская справка. О первых версиях HTML

      Консорциум W3С был создан в 1994г. и унаследовал право главенствовать в мире Интернета от Европейского института физики частиц. Первый проект – создание HTML 2.0 (формы). Второй проект – HTML 3.0 (таблицы, рисунки и т.п.) + CSS (визуальное оформление HTML-документов).

      HTML версии 1.2 содержал около 40 тэгов и не подразумевал какого-либо описания физического представления документов. Все было приведено к логической и структурной разметке текста. Только несколько тэгов (кстати, не рекомендованных для использования) издали намекали на физические свойства представления страниц. В описании одного из этих тэгов было сказано: "При просмотре документа, созданного с использованием данного тэга текст может отображаться в графических браузерах полужирным курсивом".

      CSS – каскадные таблицы стилей

      CSS1.0 вышла в 1996. Главная цель: заменить многократное использование тегов форматирования на лаконичные CSS-стили.

      CSS (англ. Cascading Style Sheets — каскадные таблицы стилей) — технология описания внешнего вида документа, написанного языком разметки. Преимущественно используется как средство оформления веб-страниц в формате HTML и XHTML, но может применяться с любыми видами документов в формате XML, включая SVG и XUL.

      CSS используется создателями веб-страниц для задания цветов, шрифтов, расположения и других аспектов представления документа. Основной целью разработки CSS являлось разделение содержимого (написанного на HTML или другом языке разметки) и представления документа (написанного на CSS). Это разделение может увеличить доступность документа, предоставить большую гибкость и возможность управления его представлением, а также уменьшить сложность и повторяемость в структурном содержимом. Кроме того, CSS позволяет представлять один и тот же документ в различных стилях или методах вывода.

      CSS при отображении страницы может быть взята из различных источников:

      1. внешних таблиц стилей, то есть отдельного файла.css, на который делается ссылка в документе.
      2. встроенных стилей — блоков CSS внутри самого HTML-документа. Данный способ определения стилей идеально подходит для корректировки или внедрения стилей в отдельные HTML-документы, так как не затрагивает другие HTML-документы.
      3. inline-стилей, когда в HTML-документе информация стиля для одного элемента указывается в его атрибуте style.
      4. стандартный стиль, используемый браузером по умолчанию для представления элементов.

      Стандарт CSS определяет приоритеты, в порядке которых применяются правила стилей, если для какого-то элемента подходят несколько правил одновременно. Это называется «каскадом», в котором для правил рассчитываются приоритеты или «веса», что делает результаты предсказуемыми.

      Описание стиля

      s1 [,s2]
      p < font-size: 20px;>h2

      Все ниже касается внешнего или встроенного описания стиля. Inline-описание выглядит так:

      Текст абзаца

      Таблица стилей состоит из набора правил. Каждое правило, в свою очередь, состоит из одного или нескольких селекторов, разделённых запятыми и блока определений. Блок определений же обрамляется фигурными скобками, и состоит из набора свойств и их значений.

      Схематически это можно показать так:

      селектор, селектор
      p < font-family: "Garamond", serif; >h2 < font-size: 110 %; color: red; background: white; >.note < color: red; background: yellow; font-weight: bold; >p#paragraph1 < margin: 0; >a:hover < text-decoration: none; >#news p

      Здесь приведено шесть правил с селекторами p, h2,.note, p#paragraph1, a:hover и #news p.

      В первых двух правилах HTML-элементам p (параграфу) и h2 (заголовку второго уровня) назначаются стили. Параграфы будут отображаться шрифтом Garamond, или, если такой шрифт недоступен, каким-либо другим шрифтом с засечками («serif»). Заголовок второго уровня будет отображаться красным на белом фоне с увеличенным кеглем.

      Третье правило будет применено к элементам, атрибут class которых содержит слово 'note'. Например:

      Этот параграф будет выведен полужирным шрифтом красного цвета на желтом фоне.

      Четвертое правило будет применяться только к элементам p, атрибут id которых равен paragraph1. Такие элементы не будут иметь внешних отступов (margin).

      Пятое правило определяет стиль hover для гиперссылок. По умолчанию в большинстве браузеров текст гиперссылок подчеркивается. Это правило уберёт подчеркивание, когда указатель мыши находится над ними.

      Последнее, шестое правило, применяется для элементов p, которые находятся внутри элемента с атрибутом id, равным «news».

      Когда CSS используется вместе с XHTML, имена элементов и селекторы становятся чувствительны к регистру.

      До изобретения CSS нужного расположения элементов на веб-странице добивались, применяя невидимые таблицы и массу тегов типа  . В CSS можно явно указывать расположение элементов.

      Способы связывания с документом

      Внешние таблицы стилей – в отдельном css-файле. Связывается с HTML-документом командой внутри заголовка.

      Встроенные – в теге в заголовке HTML-документа Inline: Пример использования CSS

      HTML:

      CSS-файл: .mystyle1

      JavaScript

      Историчская справка. О появлении JavaScript.

      JavaScript впервые появился в Netscape 2.0 в 1996 г. Написан Бренданом Эйчем. В этом же году Netscape передал JavaScript Европейской Ассоциации Компьютерных Производителей для стандартизации.

      Программы на JavaScript встраиваются в веб-страницу и могут как угодно менят ее содержимое.

      function FirstFunction() < document.myForm1.myText.value ="Вы нажали первую кнопку";>function SecondFunction()

      DOM

      DOM (Document Object Model — объектная модель документов) — это не зависящий от платформы и языка программный интерфейс, позволяющий программам и скриптам получить доступ к элементам документа, а также изменять содержимое, структуру и оформление документа.

      HTML-документ имеет иерархическую структуру, которая представлена в DOM в виде дерева, узлами которого являются теги и текст. Вложенным HTML-тегам соответствуют вложенные узлы дерева.

      Модель DOM не накладывает ограничений на структуру документа. Любой документ известной структуры с помощью DOM может быть представлен в виде дерева узлов, каждый узел которого содержит элемент, атрибут, текстовый, графический или любой другой объект. Узлы связаны между собой отношениями родитель-потомок.

      Изначально различные браузеры имели собственную модель DOM, не совместимую с остальными. Для того, чтобы обеспечить взаимную и обратную совместимость, специалисты международного консорциума W3C классифицировали эту модель по уровням, для каждого из которых была создана своя спецификация. Все эти спецификации объединены в общую группу, носящую название W3C DOM.

        ФПЖ  

      Факультет психологии животных

      О нас

      Персонал

      Это дерево представляет собой нормализованный DOM, в котором не создаются узлы из пустого текста. Такого подхода придерживается браузер Internet Explorer. Firefox другого мнения, он создает DOM-элемент из каждого текстового фрагмента. Внутри , между тегами и

      ,

      и

      ,

      и

      ,

      и можно ведь помещать любой текст. Этим пустым местам соответствуют узлы дерева слева и справа от

      и

      . Opera же может добавить лишний пустой элемент просто «от щедрой души». На практике эта несовместимость не создает больших проблем, но нужно о ней помнить и делать необходимые проверки.

      У каждого узла в DOM-модели есть тип. Всего в DOM различают 12 типов узлов. Его номер типа хранится в атрибуте elem.nodeType. Часто используются: Node.ELEMENT_NODE, номер которого равен 1. Узлам этого типа соответствуют HTML-тэги. Иногда полезен еще тип Node.TEXT_NODE, номер которого равен 3. Это текстовые элементы.

      Любой доступ и изменения DOM происходит через объект document. Например: document.body. Свойства firstChild и lastChild показывают на первый и последний дочерние элементы и равны null, если детей нет. Свойство parentNode указывает на родителя. Например, для таким элементом является . Свойства previousSibling и nextSibling указывают на левого и правого братьев узла.

      Некоторые из свойств элементов доступны только на чтение, другие — на чтение и запись. Например, свойство tagName есть у элементов-тэгов, содержит имя тэга в верхнем регистре и доступно только для чтения. style — свойство управляющее CSS-стилем, оно доступно на запись, например, можно установить element.style.width=50px. innerHTML содержит весь HTML-код внутри узла, и его можно менять. Применяется, в основном, для динамического изменения содержания страницы. onclick, onkeypress, onfocus. и другие свойства, начинающиеся на «on», хранят функции-обработчики соответствующих событий.

      AJAX

      AJAX (Asynchronous Javascript and XML — асинхронный JavaScript и XML) — подход к построению интерактивных пользовательских интерфейсов веб-приложений, заключающийся в «фоновом» обмене данными браузера с веб-сервером. В результате при обновлении данных веб-страница не перезагружается полностью, и веб-приложения становятся более быстрыми и удобными.

      CMS

      CMS (Content Management System) – система управления содержимым сайта. Позволяет управлять текстовым и графическим наполнением веб-сайта, предоставляя пользователю удобные инструменты хранения и публикации информации.

      Электронная почта

      Основные компоненты эектронной почты
      • почтовые клиенты пользователей;
      • почтовые серверы;
      • протокол отправки почты: SMTP;
      • протоколы доступа к почтовому ящику: POP3 или IMAP.

      MS Outlook
      Mozilla Thunderbird

      Клиенты
      Функции клиента
      • отправка и получение почты;
      • создание, редактирование писем;
      • просмотр писем.
      Популярные клиенты
      • Microsoft Outlook (входит в MS Office);
      • Mozilla Thunderbird (бесплатная);
      • The Bat (платная).
      Почтовые серверы
      Функции сервера
      • хранение писем пользователей (почтовые ящики);
      • отправка писем почтовому серверу получателя или клиенту пользователя (MTA, MDA);
      • организация очереди сообщений.

      Используют протокол TCP. Стандартные порты: 25 — SMTP, 110 — POP3, 143 — IMAP.

      Почтовый сервер, сервер электронной почты, мейл-сервер — в системе пересылки электронной почты так обычно называют агент пересылки сообщений (англ. mail transfer agent, MTA). Это компьютерная программа, которая передаёт сообщения от одного компьютера к другому.

      Обычно почтовый сервер работает «за кулисами», а пользователи имеют дело с другой программой — клиентом электронной почты (англ. mail user agent, MUA).

      MDA (Mail Delivery Agent, агент доставки сообщений) — программа, доставляющая сообщения на электронный ящик получателя.

      К примеру, в распространённой конфигурации агентом пользователя является Outlook Express. Когда пользователь набрал сообщение и посылает его получателю, почтовый клиент взаимодействует с почтовым сервером, используя протокол SMTP. Почтовый сервер отправителя взаимодействует с почтовым сервером получателя (напрямую или через промежуточный сервер-релей). На почтовом сервере получателя сообщение попадает в почтовый ящик, откуда при помощи агента доставки сообщений доставляется клиенту получателя. Часто последние два агента совмещены в одной программе (к примеру, sendmail), хотя есть специализированные MDA, которые в том числе занимаются фильтрацией спама. Для финальной доставки полученных сообщений используется не SMTP, а другой протокол — часто POP3 или IMAP — который также поддерживается большинством почтовых серверов. Хотя в простейшей реализации MTA достаточно положить полученные сообщения в личный каталог пользователя в файловой системе центрального сервера («почтовый ящик»).

      Популярные серверы
      • Sendmail (бесплатный, Linux / Windows)

      ExchangeServer Sendmail

      Программный пакет qmail, написанный Дэном Бернстейном (Dan Bernstein), является полноценным заменителем программного пакета sendmail. Основное внимание при его создании уделялось вопросам надежности и безопасности — двум довольно впечатляющим целям. Дэн организовал в Internet свой сервер на базе qmail и объявил приз в $1000 тому, кто сможет взломать его защиту. На момент написания книги никто не обратился за этой премией. Кроме того, в qmail предлагается улучшенный метод помещения корреспонденции в электронные почтовые ящики пользователей с использованием нового формата почтового ящика, более устойчивого к сбоям в системе. Возможно, главным преимуществом qmail является простота конфигурирования. Для ее настройки используются простые текстовые файла в формате ASCII. Программа qmail является удачным выбором для простого почтового сервера.

      Microsoft Exchange Server

      Платформа для организации корпоративной системы электронной почты и групповой работы от корпорации Microsoft. Ориентирована, прежде всего, на крупных заказчиков, однако имеется и версия для небольших предприятий (в составе Microsoft Windows Small Business Server). Главная особенность продукта — тесная интеграция с инфраструктурой Microsoft и, в частности, со службой каталогов Active Directory.

      Система Postfix была создана Вейтсом Венемой (Wietse Venema), разработчиком исследовательского центра IBM им. Томаса Уотсона (IBM Thomas J. Watson Research Center), в конце 90-х годов прошлого века. Задумывалась как более простая, безопасная и быстрая альтернатива Sendmail. Postfix имеет продуманную модульную архитектуру — каждый модуль (демон) отвечает за минимальный набор простых функций. Как следствие, обеспечивается изолированность процессов (что положительно сказывается на безопасности), а также более высокая скорость работы в режиме простоя (за счет выгрузки ненужных модулей).

      Система Exim была создана в 1995 году сотрудником Университета Кэмбриджа (University of Cambridge) Филиппом Хейзелом (Philip Hazel). Как и Sendmail, Exim имеет монолитную архитектуру, которая считается менее безопасной, чем модульная. Однако в отличие от Sendmail, Exim пока не испытывал серьезных проблем с безопасносностью. Ключевая особенность Exim заключается в логичной и прозрачной схеме обработки почты. Создатели продукта отказались от реализации ряда экзотических функций, что положительно отразилось на простоте решения. Кроме того, Exim считается быстрее и безопаснее все того же Sendmail. Exim входит в состав ряда дистрибутивов Linux/Unix систем. Поставляется по свободной лицензии GNU GPL.

      Как происходит доставка писем?

      Доставка писем

      Рассмотрим процесс доставки писем на примере. Пусть Алиса хочет отправить письмо Бобу.

      1. Почтовая программа Алисы (т.е. клиент или MUA – Mail User Agent ) отправляет письмо Бобу, ящик которого расположен на почтовом сервере в домене b.org.
      2. По протоколу SMTP (Simple Mail Transfer Protocol) клиент Алисы посылает сообщение на ее почтовый сервер (smtp-сервер). Сервер помещает сообщение в очередь для отправки адресату.
      3. SMTP-сервер Алисы узнает IP-адрес почтового сервера Боба, делая DNS-запрос типа MX для зоны b.org.
      4. SMTP-сервер Алисы по протоколу SMTP посылает почтовому северу Боба сообщение. При этом SMTP-сервер Алисы выступает в роли клиента.
      5. Почтовый сервер (Боба) помещает полученное сообщение в почтовый ящик Боба.
      6. Почтовый клиент Боба забирает письмо с сервера по протоколу POP3 или IMAP.
      Протокол SMTP

      Протокол SMTP используется для транспортировки электронной почты на почтовый сервер. Работает поверх TCP, стандартный порт сервера 25. Команды – обычный ASCII текст.

      Посылка почты осуществляется в 3 этапа:

      1. приветствие (рукопожатие);
      2. пересылка писем;
      3. закрытие сессии.
      Пример SMTP-сессии
      Server:220 Mail.Ru ESMTP Client: HELO me.ru Server: 250 mx24.mail.ru ready to serve Client: MAIL FROM: Server: 250 OK Client: RCPT TO: Server: 250 OK Client: DATA Server: 354 Go ahead Client: Privet, Gena. Pozdravlyau tebya s dnem rojdeniya … . Server: 250 Message accepted for delivery Client: QUIT Server: 221 mx24.mail.ru closing connection $ telnet mxs.mail.ru 25 // подключаемся к 25 порту почтового сервера домена mail.ru Trying 194.67.23.20. Connected to mxs.mail.ru. Escape character is '^]'. 220 Mail.Ru ESMTP // приветствие от mxs.mail.ru HELO me.ru // приветствие от меня ( me.ru -выдумка) 250 mx24.mail.ru ready to serve // всегда готов! – от mx24.mail.ru MAIL FROM: // я: отправляю письмо от себя (почтовый адрес -выдумка) 250 OK //mail.ru: понятно RCPT TO: // я: получатель – мой почтовый ящик на mail.ru 250 OK //mail.ru: такой почтовый ящик имеется DATA //я: посылаю данные 354 Go ahead //mail.ru: давай! Privet, Gena. Pozdravl yau tebya s dnem rojdeniya … // я: текст письма . // я: единственная точка на строке -конец письма 250 Message accepted for delivery //mail.ru: Сообщение принято для доставки QUIT //я: конец 221 mx24.mail.ru closing connection //mail.ru: закрываю соединение

      На самом деле было так:

      Server:220 Mail.Ru ESMTP Client: HELO me.ru Server: 250 mx24.mail.ru ready to serve Client: MAIL FROM: Server: 250 OK Client: RCPT TO: Server: 250 OK Client: DATA Server: 354 Go ahead Client: Privet, Gena. Pozdravlyau tebya s dnem rojdeniya … . Server: 550 spam message discarded. If you think that the system is mistaken, please report details to abuse@corp.mail.ru Client: QUIT Server: 221 mx24.mail.ru closing connection

      На самом деле после посылки сообщения серверу был получен такой ответ:

      550 spam message discarded. If you think that the system is mistaken, please report details to abuse@corp.mail.ru //mail.ru: это спам! Жалобы посылайте на адрес: // оскорбления @corp.mail.ru

      Проблема скрывается в формате нашего письма: отсутствует заголовок с полями From, To и Subject. Поэтому mail.ru расценивает это как спам.

      Формат сообщения электронной почты

      Сообщение электронной почты – это набор символов в семиразрядной кодировке ASCII (начинается с нуля (0-127)). Символы кодируются битами.

      From: // обязательное поле To: // обязательное поле Subject: // необязательное поле CC: // необязательное поле BCC: (это «слепая копия», то есть получатели не знают, что это письмо отправлено еще кому–то) // необязательное поле

      Если требуется передать символы, отличающиеся от ASCII, то используется кодирование. После получения сообщения сервер добавляет в заголовок строчку:

      Received: from < отправитель >by < получатель >

      Пример
      From: drug@yandex.ru To: gena@mail.ru Subject: Pozdravlyau! Privet, Gena. Pozdravlyau tebya s dnem rojdeniya … .
      Кодирование сообщений

      MIME (Multipurpose Internet Mail Extension – многоцелевое расширение почты Интернета) — стандарт, описывающий передачу различных типов данных по электронной почте.

      В заголовок сообщения добавляются строки:

      MIME–Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=“Windows-1251”

      Поле заголовка Content-Type идентифицирует данные, заключенные в MIME-сообщение. В настоящее время используется семь основных классов данных, идентифицированных в MIME. В каждом классе имеются свои подклассы, которые более детально характеризуют тип данных, заключенных в сообщении.

      Часто встречающиеся значения поля Content -Type (формат: Content -Type: тип / подтип; параметры):

      • text / html или text/ enriched (с форматированием);
      • image / gif или image/jpeg;
      • multipart / mixed (для сообщений с вложениями).

      Чтобы передавать сообщение не только из семибитной ASCII, используется кодирование.

      Часто встречающиеся значения поля Content–Transfer–Encoding:

      • 7bit;
      • 8bit;
      • binary;
      • base64;
      • quoted-printable.

      Например, 8bit или base 64.

      При кодировании увеличивается размер (как минимум, на 25%).

      На сегодняшний день существует семь различных способов кодирования двоичных данных, однако наиболее часто встречается кодирование base64. При применении этого метода кодирования 6-битовые блоки двоичных данных преобразуются в 8-битовые блоки, воспринимаемые как текст ASCII. Таким образом, в base 64 для кодирования 3 байтов (24 бита) используются 4 байта (32 бита).

      Значения Content-Transfer-Encoding "7bit", "8bit" и "binary" означают, что никакого преобразования не произведено.

      Base64. В формате электронной почты MIME base64 — это схема, по которой произвольная последовательность байт преобразуется в последовательность печатных ASCII символов. Это определяет MIME как транспортное кодирование содержимого для использования в электронной почте. Используются только символы латинского алфавита в верхнем и нижнем регистре — символы (A—Z, a—z), цифры (0—9), и символы «+» и «/», с символом «=» в качестве специального кода суффикса.

      Полная спецификация этой формы base64 содержится в RFC 1421 и RFC 2045. Эта схема используется для кодирования последовательности октетов (байт). Это соответствует определению файлов почти во всех системах. Результирующие закодированные по base64 данные имеют длину, большую оригинальной в соотношении 4:3, и напоминают по виду случайные символы.

      Для того, чтобы преобразовать данные в base64, первый байт помещается в самые старшие восемь бит 24-битного буфера, следующие в средние восемь и третий в младшие значащие восемь бит. Если кодируется менее чем три байта, то соответствующие биты буфера устанавливаются в ноль. Далее каждые шесть бит буфера, начиная с самых старших, используются как индексы строки «ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123 456789+/» и её символы, на которые указывают индексы, помещаются в выходную строку. Если кодируются только один или два байта, используются только первые два или три символа строки и выходная строка дополняется двумя или одним символами «=». Это предотвращает добавление дополнительных битов к восстановленным данным. Процесс повторяется над оставшимися входными данными.

      Например, исторический слоган Википедии,

      Man is distinguished, not only by his reason, but by this singular passion from other animals, which is a lust of the mind, that by a perseverance of delight in the continued and indefatigable generation of knowledge, exceeds the short vehemence of any carnal pleasure.

      закодирован в base64 следующим образом:

      TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFz b24sIGJ1dCBieSB0 aGlzIHNpbmd1bGFyIHBhc3Npb24gZnJvbSBvdGhlciBhbmltYWxzLCB3aGl jaCBpcyBhIGx1 c3Qgb2YgdGhlIG1pbmQsIHRoYXQgYnkgYSBwZXJzZXZlcmFuY2Ugb2Yg ZGVsaWdodCBpbiB0 aGUgY29udGludWVkIGFuZCBpbmRlZmF0aWdhYmxlIGdlbmVyYXRpb24 gb2Yga25vd2xlZGdl LCBleGNlZWRzIHRoZSBzaG9ydCB2ZWhlbWVuY2Ugb2YgYW55IGNhcm 5hbCBwbGVhc3VyZS4=

      Дополнения (attachments)

      From: drug@yandex.ru To: gena@mail.ru Subject: Pozdravlyau! MIME-Version: 1.0 Content-Type: multipart/mixed; boundary=“----------F9876678DDB9” ----------F9876678DDB9 Content-Type: text/plain; charset=Windows-1251 Content-Transfer-Encoding: 8bit Privet, Gena. ----------F9876678DDB9 Content-Type: image/jpg; name=“otkritka.jpg” Content-transfer-encoding: base64 Content-Disposition: attachment; filename=“otkritka.jpg” base64 encoded data. ----------F9876678DDB9

      Доступ к письмам в почтовом ящике

      Доступ к письмам в почтовом ящике может осуществляться по протоколам:

      • POP3 (Post Office Protocol) порт сервера 110; авторизация и скачивание сообщений с сервера; «толстый почтовый клиент».
      • IMAP (Internet Mail Access Protocol [RFC 1730]) порт сервера 143; больше возможностей, более сложный; позволяет управлять сообщениями на сервере; «тонкий почтовый клиент».
      • HTTP используется на mail.ru, yandex.ru, gmail.com; «сверхтонкий почтовый клиент».
      Протокол POP3
      S: +OK C: USER kto_to S: +OK Password required for user kto_to C: PASS 123456 S: +OK C: STAT S: +OK 118 6286336 C: LIST S: +OK 118 messages (6286336 octets) 1 1203 2 534 3 1200432 и т.д.

      POP 3 – это текстовый протокол.

      Команды клиента

      Комбинация команд USER/PASS — самая простая в реализации, но в то же время самая опасная с точки зрения безопасности. Каждый раз при соединении клиента с сервером POP3 с целью проверки почты по сети посылается его идентификатор пользователя и пароль в виде текста в формате ASCII. Это просто находка для хакера! Один из выходов – использовать команду APOP и посылать пароль в зашифрованном виде, однако

      APOP поддерживают не все серверы (судя по первому ответу сервера, mail.ru не поддерживает APOP. В противном случае он бы послал ключ). Другой выход, используемый gmail.com – безопасные (зашифрованные) соединения по протоколу SSL ( это вдвойне хорошо: от хакеров защищен как процесс авторизации так и прием отдельных сообщений ).

      STAT Команда STAT применяется для получения текущего состояния почтового ящика пользователя. LIST Команда LIST используется для получения развернутого листинга почтового ящика. Развернутый листинг представляет собой краткое содержание почтового ящика, включая номер и объем сообщения в байтах. Когда команда LIST задается без параметров, то отображается развернутый листинг всех сообщений в почтовом ящике. Если же использовать в качестве параметров команды номер сообщения, то развернутый листинг будет производиться только для него.

      UIDL Необязательная для всех серверов POP3 команда. Благодаря ей все сообщения, хранящиеся на сервере, получают уникальные номера, которые сохраняются для всех сеансов POP3. Как уже говорилось ранее, сообщения нумеруются по порядку в течение сеанса POP3. По завершении клиентом сеанса и с началом нового сеанса сообщения перенумеровываются. Таким образом, если клиент имел в своем ящике десять сообщений и удалил шестое сообщение в течение сеанса, то при следующем сеансе POP3 девять сообщений будут перенумерованы с первого по девятое. Как видите, у клиентского программного обеспечения довольно непростая задача — следить за перенумерацией сообщений. Для решения этой проблемы в некоторые серверы POP3 встроена поддержка команды UIDL или “листинг с уникальным идентификатором”. Каждому сообщению назначается уникальный идентификатор, который представляет собой строку символов формата ASCII (до 70 символов). Этот идентификатор сохраняется за сообщением все время, пока оно находится в почтовом ящике

      RETR Команда RETR используется для получения сообщений из почтового ящика на компьютер клиента. Параметр, который можно использовать с этой командой, — это номер сообщения, полученный с помощью команды LIST.

      DELE Команда DELE используется для удаления сообщений из почтового ящика на сервере. Единственный параметр, который можно в ней задавать, — это номер сообщения, полученный с помощью команды LIST. Команда DELE физически не удаляет сообщение, она лишь помечает его для удаления. Удаление сообщения происходит лишь после корректного завершения сеанса с помощью команды QUIT.

      TOP [сообщение] [количество строк] – есть такая команда! на лекции я ошибся! Сервер возвращает заголовки указанного сообщения, пустую строку и указанное количество первых строк тела сообщения.

      QUIT Команда QUIT используется для завершения сеанса POP3. Когда сервер получает команду QUIT, то он удаляет все помеченные для удаления в течение сеанса сообщения и закрывает TCP-соединение. Если сеанс POP3 завершить до того, как клиент выдаст команду QUIT, то все помеченные для удаления сообщения будут сохранены и удаляться не будут.

      Ответы сервера начинаются с символов +OK и –ERR. Конец многострочного ответа обозначается строкой с одной точкой (.).

      C: UIDL S: +OK 118 messages (6286336 octets) 1 4323549873 2 5243509832 3 9653582120 и т.д. . C: RETR 115 S: +OK 2259 octets сообщение . C: DELE 115 C: QUIT S: +OK POP3 server at mail.ru signing off
      Протокол IMAP
      • Письма хранятся на сервере, а не на клиенте. Клиент запрашивает только заголовки писем.
      • Возможен доступ (даже одновременный) к одному и тому же почтовому ящику с разных клиентов.
      • Возможно создание общих папок, к которым могут иметь доступ несколько пользователей.
      • Поддержка поиска на сервере.
      • Поддержка онлайн-работы.

      Аналогичен POP3, т.е. служит для работы со входящими письмами, однако обеспечивает дополнительные функции, в частности, возможность провести поиск по ключевому слову, не сохраняя почту в локальной памяти. При использовании протокола IMAP не скачиваются сразу все письма. Почтовый клиент сначала получает заголовки писем, а сами письма запрашивает по мере необходимости. Таким образом протокол IMAP поможет в работе с почтой пользователям с плохой скоростью интернет-связи.

      IMAP предоставляет пользователю богатые возможности для работы с почтовыми ящиками, находящимися на центральном сервере. Почтовая программа, использующая этот протокол, получает доступ к хранилищу корреспонденции на сервере так, как будто эта корреспонденция расположена на компьютере получателя. Электронными письмами можно манипулировать с компьютера пользователя (клиента) без необходимости постоянной пересылки с сервера и обратно файлов с полным содержанием писем. Для отправки писем используется протокол SMTP. Gmail и mail.ru поддерживают IMAP

      Преимущества IMAP
      • Письма хранятся на сервере, а не на клиенте. Возможен доступ к одному и тому же почтовому ящику с разных клиентов. Поддерживается также одновременный доступ нескольких клиентов. В протоколе есть механизмы с помощью которых клиент может быть проинформирован об изменениях, сделанных другими клиентами.
      • Поддержка нескольких почтовых ящиков (или папок). Клиент может создавать, удалять и переименовывать почтовые ящики на сервере, а также перемещать письма из одного почтового ящика в другой.
      • Возможно создание общих папок, к которым могут иметь доступ несколько пользователей.
      • Информация о состоянии писем хранится на сервере и доступна всем клиентам. Письма могут быть помечены как прочитанные, важные и т. п.
      • Поддержка поиска на сервере. Нет необходимости скачивать с сервера множество сообщений для того чтобы найти одно нужное.
      • Поддержка онлайн-работы. Клиент может поддерживать с сервером постоянное соединение, при этом сервер в реальном времени информирует клиента об изменениях в почтовых ящиках, в том числе о новых письмах.
      • Предусмотрен механизм расширения возможностей протокола.
      Доступ к электронной почте через веб-интерфейс
      • Клиент пользователя – веб-браузер.
      • Письмо передается веб-серверу по протоколу HTTP (в виде содержимого HTML-форм).
      • Веб-сервер вызывает CGI-скрипт (или др.), который отправляет письмо адресату.
      • Пример: при нажатии кнопки «Отправить» на сайте mail.ru вызывается скрипт /cgi-bin/sentmsg.

      Сведения о mail.ru получены при помощи сниффера.

      Спам

      Виды
      • Реклама
      • Антиреклама
      • Нигерийские письма

      Иногда спам используется для того, чтобы выманить деньги у получателя письма. Наиболее распространенный способ получил название «нигерийские письма», потому что большое количество таких писем приходило из Нигерии. Такое письмо содержит сообщение о том, что получатель письма может получить каким-либо образом большую сумму денег, а отправитель может ему в этом помочь. Затем отправитель письма просит перевести ему немного денег под предлогом, например, оформления документов или открытия счета. Выманивание этой суммы и является целью мошенников.

      (англ. phishing от fishing — рыбалка) (автоматический поиск email-адресов)

      Средства борьбы
      • Фильтрация

      Историческая справка. Борьба со спамом на законодательном уровне

      С 1 января 2004 года в США действует федеральный закон, получивший название Can-Spam Act. Делаются попытки привлечь спамеров к суду, и иногда такие попытки оказываются успешными.

      Американец Роберт Солоуэй проиграл процесс в федеральном суде против небольшой оклахомской фирмы-провайдера интернет-услуг, оператор которой обвинил его в рассылке спама. Приговор суда включал в себя возмещение убытков в размере $10 075 000.

      Первый случай, когда пользователь выиграл дело против компании, занимавшейся рассылкой спама, имел место в декабре 2005, когда бизнесмен Найджел Робертс с острова Олдерни (Нормандские острова) выиграл суд против Media Logistics UK, получив в качестве компенсации 270 £

      Интересен пример истории с российским провайдером Majordomo, заблокированным за рассылки спама, якобы ведшиеся с принадлежавших ему адресов.

      Принимаемые законы по борьбе со спамом могут противоречить конституции. Так Верховный Суд Вирджинии отменил приговор спамеру Джереми Джейнсу и признал неконституционным закон о борьбе со спамом как нарушающий право на свободу слова.

      Служба передачи файлов FTP

      Протокол FTP (File Transfer Protocol — протокол передачи файлов) обеспечивает

      • просмотр содержимого каталогов;
      • передачу файлов на сервер и обратно.

      Клиентом выступает тот, кто инициирует передачу (веб-браузер, plugin’ы в файловых менеджерах, проводник, CuteFtp. ). Распространенные FTP-серверы: ftpd, Serv-U, Titan FTP Server, freeFTPd. Стандартный порт сервера: 21. Запрос в браузере: ftp://user:password@ftp.server.ru

      Историческая справка. FTP

      FTP является одним из старейших прикладных протоколов, появившимся задолго до HTTP, в 1971 году. До начала 90-х годов на долю FTP приходилось около половины трафика в сети Интернет. Он и сегодня широко используется для распространения ПО и доступа к удалённым хостам.

      Клиент FTP в Total Commander

      Чтобы установить TCP соединение с сервером (FTP для передачи данных использует транспортный протокол TCP) из браузера достаточно в строке адреса явно указать протокол: ftp://sun.mmcs.rsu.ru. Это будет означать, что имя пользователя – anonymous. Если ftp-сервер не допускает анонимной авторизации, браузер запросит у вас логин и пароль, также их можно явно указать в строке адреса: ftp://user:password@ sun.mmcs.rsu.ru.

      Схема работы

      Схема взаимодействия FTP-клиента и FTP-сервера

      1. FTP-сеанс начинается с установления FTP-клиентом управляющего TCP-соединения с удаленным хостом (сервером) через порт с номером 21.
      2. Клиент авторизуется.
      3. Клиент просматривает содержимое каталогов на удаленном сервере, посылая соответствующие команды.
      4. Когда сервер получает команду «Передать файл», он открывает новое TCP-соединение (т.н. соединение данных) с клиентом, по которому затем происходит передача.
      5. После окончания передачи сервер закрывает соединение данных.

      По установленному соединению осуществляется передача имени пользователя и пароля, а также команд смены текущего каталога и обмена файлами. Протокол не шифруется, при аутентификации передаёт логин и пароль открытым текстом. Если злоумышленник находится в одном сегменте сети с пользователем FTP, то, используя сниффер, он может перехватить логин и пароль пользователя, или, при наличии специального ПО, получать передаваемые по FTP файлы без авторизации. Чтобы предотвратить перехват трафика, необходимо использовать протокол шифрования данных SSL, который поддерживается многими современными FTP-серверами и некоторыми FTP-клиентами.

      Протокол FTP использует два параллельных TCP-соединения: управляющее соединение и соединение данных. Управляющее соединение служит для пересылки управляющей информации между двумя хостами: имени пользователя и пароля, команд смены текущего удаленного каталога, передачи и запроса файлов. Соединение данных предназначено для передачи самих файлов. Поскольку управляющее соединение отделено от соединения данных, говорят, что передача управляющей информации осуществляется вне полосы (out-of-band). В отличие от FTP, протокол HTTP использует одно соединение для управляющих команд (в заголовке) и данных, т.е. HTTP передает свою управляющую информацию внутри полосы (in-band). Когда сервер получает команду передачи или приема файла, он устанавливает с клиентом TCP-соединение данных, затем осуществляет файловый обмен и закрывает соединение. Каждое соединение позволяет передать только один файл; таким образом, множественный обмен вызывает необходимость многократной установки соединения данных. При этом управляющее соединение остается открытым в течение всего сеанса и во время передачи файла по соединению данных управляющее соединение не используется.

      Команды клиента и ответы сервера
      S: 220 r321-01.mmcs.rsu.ru FTP server (NetBSD-ftpd) ready. C: USER kto-nibud S: 331 Password required for kto-nibud. C: PASS 1234567 S: 230- FreeBSD 7.0-RELEASE (GENERIC) #0: Feb 24 10:35:36 Welcome to FreeBSD! S: 230 User kto-nibud logged in. C: SYST S: 215 UNIX Type: L8 Version: NetBSD-ftpd 20051124 C: PWD S: 257 "/home/guda" is the current directory. C: PASV S: 227 Entering Passive Mode (212,193,209,241,240,214)
      Активный и пассивный режимы работы

      Клиент инициирует TCP-соединение с динамического порта (1024-65535) к порту номер 21 на FTP-сервере. Дальнейшие действия зависят от того, какой режим FTP (активный или пассивный) выбран. В активном режиме клиент также сообщает серверу номер порта (из динамического диапазона 1024-65535) для того, чтобы сервер мог подключиться к клиенту для установки соединения для передачи данных. FTP-сервер подключается к заданному номеру порта клиента, используя со своей стороны номер TCP-порта 20 для передачи данных. Для клиента такое соединение является входящим, так что зачастую работа в активном режиме клиентов, находящихся за файрволлом или NAT затруднена или требует дополнительных настроек. В пассивном режиме, после того как клиент инициировал сединение, сервер сообщает клиенту номер TCP-порта (из динамического диапазона 1024-65535), к которому можно подключится для установки соединения передачи данных. При этом порты в таком соединении как со стороны клиента, так и со стороны сервера оказываются произвольными. В пассивном режиме клиент легко может работать с сервером сквозь свой файрволл, но зачастую для поддержки пассивного режима сервером требуется соответствующая настройка файрволла уже на стороне сервера.

      Главное отличие между активным режимом FTP и пассивным режимом — это сторона, которая открывает соединение для передачи данных. В активном режиме клиент должен суметь принять это соединение от FTP-сервера, в пассивном же клиент всегда инициирует это соединение сам, и принять его должен уже сервер.

      Потоковое мультимедиа

      Потоковое – это радио, телевидение. Не потоковое – книги, видеокассеты, DVD- диски. Attempts to display media on computers date back to the earliest days of computing, in the mid-20th century. However, little progress was made for several decades, primarily due to the high cost and limited capabilities of computer hardware.

      From the late 1980's through the 1990's, consumer-grade personal computers became powerful enough to display various media. The primary technical issues with streaming were:

      • having enough CPU power and bus bandwidth to support the required data rates;
      • creating low-latency interrupt paths in the OS to prevent buffer underrun.

      However, computer networks were still limited, and media was usually delivered over non-streaming channels, such as CD-ROMs. The late 1990's and 2000's, internet users saw:

      • greater network bandwidth, especially in the last mile;
      • increased access to networks, especially the Internet;
      • use of standard protocols and formats, such as TCP/IP, HTTP, and HTML;
      • commercialization of the Internet.

      These advances in computer networking combined with powerful home computers and modern operating systems made streaming media practical and affordable for ordinary consumers. Stand-alone Internet radio devices are offering listeners a "no-computer" option for listening to audio streams.

      In general, multimedia content is large, so media storage and transmission costs are still significant; to offset this somewhat, media is generally compressed for both storage and streaming.

      A media stream can be on demand or live. On demand streams are stored on a server for a long period of time, and are available to be transmitted at a user's request. Live streams are only available at one particular time, as in a video stream of a live sporting event.

      Research in streaming media is ongoing and representative research can be found at the Journal of Multimedia (http://www.academypublisher.com/jmm/index.html) .

      Виды потокового мультимедиа
      • записанное потоковое аудио и видео;
      • потоковое аудио и видео реального времени (телерадиовещание через Интернет);
      • интерактивное аудио и видео реального времени (IP-телефония).

      Характеристики передачи мультимедиа:

      • чувствительность к задержкам пакетов;
      • устойчивость к потерям пакетов.
      Записанное потоковое аудио и видео

      К этому классу приложений относятся приложения, в которых клиент отправляет запрос на просмотр хранящегося на сервере аудио- или видеофайла, который передается ему, как правило, в сжатом виде и тут же воспроизводится.

      Этот класс приложений обладает тремя ключевыми характеристиками.

      • Сохранение мультимедийных данных на запоминающем устройстве. Аудио- или видеоданные заранее записываются и сохраняются на сервере в виде файлов. В результате пользователь может остановить, перемотать фильм вперед или назад, а также начать воспроизведение с начала любой части фильма. Время отклика системы на подобные команды пользователя не должно превышать десяти секунд.
      • Потоковое воспроизведение. В приложениях записанного потокового аудио/видео клиент может воспроизводить аудио- и видеоданные уже через несколько секунд после того, как данные начнут поступать с сервера. Это означает, что клиент воспроизводит одну часть файла, в то же время принимая по сети следующие его части. Такой метод воспроизведения, называемый потоковым, позволяет не ждать загрузки всего файла (для чего может потребоваться довольно много времени) перед его воспроизведением.
      • Непрерывное воспроизведение. Начавшись, воспроизведение мультимедиа должно продолжаться столько времени, сколько длится оригинальная запись. Это требование накладывает строгие ограничения на значение задержки в доставке данных. Данные с сервера должны доставляться вовремя. Хотя приложения записанного потокового мультимедиа предъявляют довольно высокие требования к службе доставки данных, накладываемые ими ограничения на сквозную задержку не столь строги, как для интерактивных приложений реального времени, например Интернет-телефонии или видеоконференций.
      Потоковое аудио и видео реального времени

      Этот класс приложений схож с традиционной трансляцией радио- и телепередач с той лишь разницей, что передача ведется не в эфире и не по специальному кабелю, а через Интернет. Эти приложения позволяют пользователю получать теле- или радиопрограммы из любого уголка мира. Поскольку «живое» потоковое аудио и видео не сохраняется на запоминающих устройствах, клиент не может осуществлять перемотку вперед. Однако некоторые приложения позволяют пользователю локально сохранять полученные данные и выполнять такие действия, как остановка и перемотка назад. Довольно часто у подобных радио- или телепередач бывает весьма широкая аудитория. Доставка данных сразу многим клиентам, принимающим в этот момент передачу одной и той же станции, может эффективно осуществляться путем групповой IP - маршрутизации. Однако чаще доставка мультимедийных данных выполняется путем выборочной рассылки нескольких отдельных потоков. Как и в случае записанного потокового мультимедиа, здесь требуется непрерывное воспроизведение, хотя временные ограничения не столь строги, как для интерактивных приложений реального времени. Допустимыми считаются задержки в десятки секунд от момента запроса пользователя до начала воспроизведения.

      Интерактивное аудио и видео реального времени

      Этот класс приложений дает возможность пользователям общаться друг с другом в режиме реального времени. Службу интерактивного аудио реального времени с передачей данных через Интернет часто называют Интернет-телефонией, поскольку с точки зрения пользователя она напоминает традиционную телефонную службу с коммутацией каналов. Интернет-телефония может использоваться для локальной и междугородной телефонной связи по очень низкой цене. Кроме того, Интернет-телефония позволяет упростить развертывание новых служб, которые плохо поддерживаются традиционными сетями с коммутацией каналов, таких как службы интеграции телефонии в web, видеоконференции, службы каталогов, службы фильтрации абонентов и т. д. На сегодняшний день созданы сотни программ поддержки Интернет-телефонии (http://www.von.com). Например, пользователи программы Instant Messenger компании Microsoft могут звонить с персонального компьютера на обычный телефон или с одного персонального компьютера на другой. Интерактивная видеосвязь в реальном времени (видеоконференции) позволяет пользователям не только слышать, но и видеть друг друга. Сегодня на рынке предлагается множество программных продуктов, обеспечивающих интерактивную видеосвязь через Интернет в реальном времени, включая программу NetMeeting корпорации Microsoft. Обратите внимание, что в интерактивных аудио- и видеоприложениях реального времени пользователь может двигаться и говорить. Для подобных приложений задержка в доставке данных не должна превышать нескольких десятых долей секунды. При передаче голоса задержки менее 150 мс не воспринимаются слушателем, задержки в пределах от 150 мс до 400 мс считаются приемлемыми, а задержки, превышающие 400 мс, могут восприниматься как существенные искажения и вести к неразборчивости речи.

      Простейшая реализация

      В Интернете есть множество музыкальных веб-сайтов, на многих из которых представлены списки песен, которые пользователь может прослушать, щелкнув на названии. Наиболее распространенный способ реализации такой системы «музыки по заказу» показан на рисунке. Процесс начинается, когда пользователь щелкает на названии песни. Вначале вступает в дело браузер. Первый шаг заключается в установке TCP-соединения с веб-сервером, на который указывает гиперссылка. На втором шаге ему направляется HTTP-запрос GET, содержащий заявку на получение файла. Шаги 3 и 4 выполняются сервером: он получает песню (которая представляет собой обычный файл в формате МР3 или каком-нибудь другом) с диска и отсылает ее браузеру.

      По МШЕ-типу файла (например, audio/mpЗ) или по расширению браузер определяет способ его воспроизведения. Обычно запускается вспомогательное приложение, ассоциированное с данным типом файлов, например, RealOne Player, Windows Media Player или Winamp. Обычно браузер общается со вспомогательным приложением, записывая информацию, предназначенную для воспроизведения, во временный файл. Поэтому до начала проигрывания весь музыкальный файл будет записан во временный файл на диске (шаг 5). После этого будет запущен проигрыватель, которому браузер передаст имя временного файла. Шаг 6 заключается в поблочном считывании данных из файла и непосредственном воспроизведении музыки.

      В принципе, такой подход совершенно корректен, и музыку пользователь услышит. Единственная серьезная проблема заключается в том, что вся запись должна быть предварительно передана по сети. Если музыкальный файл занимает 4 Мбайт (типичный размер аудиофайла с песней в формате МРЗ) и передается при помощи модема со скоростью 56 Кбит/с, пользователь будет наслаждаться тишиной в течение почти 10 минут, прежде чем услышит музыку. Далеко не все меломаны приходят от этого в восторг. К тому же не стоит забывать, что после окончания данной песни следующую можно будет услышать также только через 10 минут.

      Как обойти эту проблему, не внося изменений в работу браузера?

      Последовательное потоковое видео (progressive streaming)

      Проигрыватели начинают показ видео, не дожидаясь полной загрузки файла. При этом файлы по частям могут передавать обычные http-серверы. FLV-формат (Flash Live Video) содержит метаинформацию для «перемотки» видео-потока.

      • плохая навигация в больших файлах;
      • видео сохраняется у пользователя на компьютере.

      With Apache or IIS, you add HTTP streaming through a server side script, which negatively impacts performance. One web server without this performance issue is the Lighttpd web server. It includes a module for HTTP FLV streaming, so if you use this server you can HTTP stream out-of-the-box.

      Потоковое видео реального времени (со спецсерверов)

      Дополнительное серверное ПО:

      • Flash Media Server;
      • Windows Media Services;
      • QuickTime Streaming Server.
      • хорошая навигация даже для больших файлов;
      • защищенность видео данных.
      Удаленное управление потоком данных: RTSP

      Удаленное управление потоком данных: RTSP

      Музыкальные сайты пришли к следующей схеме. Файл, связанный гиперссылкой с названием песни, на самом деле является не музыкальным, а метафайлом. Метафайл обычно очень короткий, в типичной ситуации он состоит всего лишь из одной текстовой строки, которая выглядит примерно так: rtsp://joes-audio-server/song-0025.mp3 Получив такой однострочный файл, браузер записывает его во временный файл, запускает в качестве вспомогательного приложения проигрыватель и передает ему, как обычно, имя временного файла. Проигрыватель видит, что временный файл содержит URL, соединяется с сервером joes-audio-server и запрашивает песню. Браузер не принимает участия в этом процессе.

      В большинстве случаев сервер, указанный в метафайле, не совпадает с веб-сервером, содержащим ссылку на метафайл. Более того, обычно это даже не HTTP-сервер, а специализированный мультимедийный сервер. В приведенном примере этот сервер использует протокол RTSP, это становится понятно при взгляде на ссылку — она начинается с названия протокола, rtsp. RTSP описан в RFC 2326.

      Проигрыватель мультимедиа решает следующие 4 основные задачи:

      1. Управление интерфейсом пользователя.
      2. Обработка ошибок передачи.
      3. Распаковка сжатых аудиоданных.
      4. Устранение флуктуации (джиттера (в области телекоммуникаций джиттером называется первая производная задержки прохождения данных по времени)).

      При передаче музыки в реальном времени редко используется протокол TCP, так как ошибки и повторные передачи могут приводить к недопустимо долгим паузам. Вместо этого передача осуществляется по протоколу типа RTP. Подобно большинству протоколов реального времени, RTP работает поверх UDP, то есть пакеты могут теряться по пути. Проблему потерянных пакетов решает проигрыватель.

      Четвертая задача — устранение флуктуации (джиттера), бича всех систем реального времени. Все системы воспроизведения потокового аудио перед началом проигрывания буферизируют около 10-15 с. звучания. В идеале — сервер должен продолжать заполнять буфер со скоростью, необходимой для проигрывателя, однако в реальности это может и не происходить, поэтому всегда полезно иметь постоянную обратную связь.

      Синтаксис RTSP-запросов очень похож на HTTP. Порт сервера — 554.

      Команды RTSP, посылаемые проигрывателем на сервер

      DESCRIBE URL в ответ сервер перечисляет параметры мультимедийных данных
      SETUP определяет как будет транспортироваться медиа-поток. Запрос включает в себя номера двух портов для приема RTP-датаграм (аудио или видео) и RTCP-порта метаданных
      PLAY «перадать указанный промежуток медиа-файла». Данные передаются по другому соединению, по протоколу RTP. Здесь так же, как и в FTP
      RECORD «сохранить медиа-данные на сервере»
      PAUSE приостанавить передачу данных
      TEARDOWN конец соединения

      RTCP (RTP Control Protocol) — протокол, предоставляющий приложениям, работающим по протоколу RTP, механизм реагирования на изменения в сети. Например, получив информацию о повышении интенсивности трафика в сети и уменьшении выделенной этому приложению полосы пропускания, приложение может принять меры и умерить свои требования к полосе пропускания за счёт некоторой потери качества. После снижения нагрузки в сети приложение может восстановить исходную полосу пропускания и продолжить работу с тем качеством, которое оно предоставляло вначале.

      Обработка ошибок
      Проблемы при передаче мультимедиа

      Проблемы при передаче мультимедиа
      Проблемы при передаче мультимедиа. Мнение специалистов

      Развернутый сегодня в Интернете протокол IP предоставляет всем переносимым им дейтаграммам обслуживание по остаточному принципу. Другими словами, Интернет прилагает максимум усилий по перемещению каждой дейтаграммы от отправителя к получателю за минимальное время, но не предоставляет никаких гарантий относительно величины сквозной задержки для отдельных пакетов. Также никаких гарантий не предоставляется относительно изменений величины задержки доставки пакета в потоке пакетов. Поскольку в Интернете нет службы, предпринимающей специальные усилия по доставке пакетов в жесткие сроки, разработка успешно работающих мультимедийных сетевых приложений для Интернета представляет собой крайне сложную задачу. На сегодняшний день мультимедийные приложения в Интернете достигли значительного, но ограниченного успеха. Так, в приложениях для воспроизведения записанного потокового аудио и видео задержка, как правило, может составлять от 5 до 10 с. Однако в периоды пиковой нагрузки производительность таких приложений может стать неудовлетворительной, особенно если линии связи, по которым передаются мультимедийные данные (например, кабели, проложенные по дну океанов), оказываются перегруженными.

      Сегодня ведутся яростные дебаты о том, как должен развиваться Интернет, чтобы лучше приноровиться к мультимедийному трафику с его строгими временными ограничениями. На одном конце находятся исследователи, утверждающие, что в Интернете должны быть сделаны радикальные изменения, что позволило бы приложениям явным образом резервировать сквозную пропускную способность. Эти исследователи полагают, что пользователь, желающий, например, позвонить по телефону с хоста А на хост В, должен иметь возможность явно зарезервировать пропускную способность в каждой линии на всем маршруте. Но для реализации подобного подхода требуется сделать очень много. Во-первых, нужен протокол, резервирующий от имени приложений пропускную способность на маршруте от отправителя до получателя. Во-вторых, необходимо модифицировать политику планирования очередей на маршрутизаторах, чтобы те поддерживали резервирование пропускной способности.

      Другую крайнюю точку зрения представляют исследователи, утверждающие, что нет необходимости производить какие бы то ни было фундаментальные изменения в предоставляемых на сегодняшний день Интернетом услугах, а также в протоколах Интернета. Вместо этого они отстаивают политику невмешательства. По мере увеличения требований Интернет-провайдеры (как верхнего, так и нижнего звеньев) будут наращивать свои сети, чтобы удовлетворить эти новые требования. Для обработки живого потокового трафика (например, сообщений о спортивных событиях), одновременно посылаемого миллионам пользователей, могут быть развернуты групповые оверлейные сети. Групповая оверлейная сеть состоит из серверов, разбросанных по сети (и, возможно, по всему Интернету). Эти серверы и логические линии между ними образуют вместе оверлейную сеть, предназначенную для групповой рассылки данных от отправителя к миллионам пользователей. В отличие от группового протокола IP, в котором функции групповой рассылки выполняют маршрутизаторы на IP-уровне, оверлейные сети осуществляют групповую рассылку на прикладном уровне. Например, хост-источник может отправить поток трем или более оверлейным серверам; этот процесс продолжается, создавая дерево распределения поверх IP-сети с ее маршрутизаторами и хостами. Путем групповой рассылки популярного трафика по оверлейным сетям можно снизить суммарную нагрузку на Интернет еще больше.

      Между этими двумя крайними точками зрения располагаются сторонники так называемого дифференцированного обслуживания. Эти исследователи предлагают произвести в Интернете относительно небольшие изменения на сетевом и транспортном уровнях, а также добавить на периферию сети (то есть в интерфейс между пользователем и Интернет-провайдером) простые схемы ценообразования и мониторинга. Идея заключается в том, чтобы использовать небольшое количество классов трафика (возможно, будет достаточно двух классов), отмечать класс трафика в каждой дейтаграмме и предоставлять дейтаграммам различных классов разные уровни обслуживания в очередях маршрутизаторов. Разумеется, обслуживание более высокого класса будет стоить пользователю дороже.

      Потеря пакетов приводит к ухудшению качества, а не к промежуткам тишины

      Обработка ошибок при передаче музыки

      Иногда для упрощения обработки ошибок при передаче музыки применяется принцип чередования. Например, пакет может содержать 220 стереоотсчетов, каждый из которых содержит пару 16-разрядных чисел. Этого вполне достаточно для 5 мс звучания музыки. Однако протокол может посылать в одном пакете все нечетные отсчеты для 10 мс звучания, а в следующем — все четные отсчеты для того же интервала. Таким образом, потеря одного пакета не приведет к возникновению паузы длиной 5 мс, вместо этого будет потерян каждый второй отсчет 10- миллисекундного интервала. Эта утрата может быть восполнена, если проигрыватель произведет интерполяцию, используя предыдущий и следующий отсчеты (относительно каждого потерянного). Таким образом, примерные значения будут восстановлены.

      Принцип чередования, используемый для восстановления ошибок, показан на рисунке. Здесь видно, что каждый пакет содержит чередующиеся отсчеты для 10-миллисекундного интервала. В результате потери пакета 3 (см. рисунок) не возникает паузы, а только лишь на некоторое время снижается частота следования отсчетов. Утерянные значения путем интерполяции могут быть восстановлены; это обеспечит непрерывность звучания. Данная конкретная схема работает только с несжатыми отсчетами, однако она показывает, как при помощи хитрого алгоритма кодирования превращать потерянные пакеты не в раздражающие паузы, а в непрерывные интервалы с пониженным качеством. Между тем в RFC 3119 описан метод, позволяющий применять аналогичную процедуру к сжатым аудиоданным.

      IP-телефония

      Интернет-Телефония частный случай IP-Телефонии, здесь в качестве линий передачи используются обычные каналы Internet. В чистом виде IP-телефония, в качестве линий передачи телефонного трафика использует выделенные цифровые каналы;

      H.323 от ITU

      Модель архитектуры H.323 для интернет-телефонии

      С самого начала всем было понятно, что если каждый производитель станет изобретать собственный стек протоколов, система никогда работать не будет. Во избежание возникновения этой проблемы заинтересованные стороны объединились под покровительством Международного союза телекоммуникаций (ITU) и начали разработку единого стандарта. В 1996 году ITU (International Telecommunication Union - Международный союз электросвязи) выпустил рекомендации с индексом Н.323 под заголовком «Видеотелефонные системы и оборудование локальных вычислительных сетей, не предоставляющих гарантированное качество обслуживания». Такое название могло родиться только в телефонной индустрии. Данные рекомендации были пересмотрены в 1998 году, и новый вариант Н.323 стал основой построения первых глобальных систем интернет-телефонии.

      Н.323 скорее дает общее представление об архитектуре систем интернет-телефонии, нежели описывает некий конкретный протокол. В документе можно найти множество ссылок на различные специализированные протоколы кодирования речи, установки соединения, передачи сигналов, данных и т. п., однако их описание не приводится. Общая модель изображена на рисунке. В центре находится шлюз, соединяющий Интернет с телефонной сетью. Он поддерживает протокол Н.323 со стороны Интернета и протоколы коммутируемой телефонной сети общего пользования с «телефонной» стороны. Устройства коммуникации называются терминалами. В локальной вычислительной сети может быть контроллер зоны, управляющий конечными узлами, находящимися под его юрисдикцией (в его зоне).

      Терминал (terminal) — оконечное мультимедийное (голос, видео, данные) устройство, предназначенное для участия в конференции.

      Мультимедиа шлюз (gateway) — устройство, предназначенное для преобразвания мультимедийной и управляющей информации при сопряжении разнородных сетей.

      Устройство управления многоточечными конференциями (Multipoint Control Unit — MCU) предназначено для организации конференций с участием трех и более участников.

      Контроллер зоны (gatekeeper, привратник, конференц-менеджер) — рекомендуемое, но не обязательное устройство, обеспечивающее сетевое управление и исполняющее роль виртуальной телефонной станции.

      Семейство протоколов H.323

      Семейство протоколов H.323

      Работу телефонной сети обеспечивает множество протоколов. Во-первых, необходим протокол кодирования и декодирования речи. Поскольку разрешено использование нескольких алгоритмов сжатия, необходим отдельный протокол, который позволил бы терминалам договориться об использовании одного из этих протоколов. Такой протокол называется Н.245. Он позволяет согласовать также другие параметры соединения, например, битовую скорость. RTCP требуется для управления каналами RTP. Кроме того, нужны протоколы для установления и разрыва соединений, обеспечения тонального вызова, генерирования звуков звонков и других стандартных функций телефонной системы. Терминалам нужен протокол для ведения переговоров с машиной-вратарем (если такая присутствует в локальной сети). Для этого в системе работает протокол Н.225. Канал между ПК и вратарем, которым этот протокол управляет, называется каналом RAS (Registration/Admission/Status — Регистрация/Доступ/Статус). Он позволяет терминалам, кроме всего прочего, входить в зону и покидать ее, запрашивать и освобождать пропускную способность, обновлять данные о состоянии. Наконец, нужен протокол для непосредственной передачи данных. На этом участке работает RTP. Как обычно, управляется он RTCP. Иерархия всех этих протоколов показана на рисунке.

      H.323. Логические соединения между абонентами

      Логические соединения между абонентами

      Чтобы понять, как эти протоколы взаимодействуют друг с другом, рассмотрим случай ПК, являющегося терминалом локальной сети (с вратарем) и звонящего на удаленный телефон. Вначале компьютеру нужно найти вратаря, поэтому он рассылает широковещательным образом специальный UDP-пакет через порт 1718. Из ответа вратаря ПК узнает его IP-адрес. Теперь компьютер должен зарегистрироваться у вратаря. Для этого он посылает ему сообщение RAS в пакете UDP. После регистрации компьютер обращается к вратарю с просьбой (сообщение доступа RAS) о резервировании пропускной способности. Только после выделения этого ресурса можно начинать установку соединения. Предварительное резервирование пропускной способности позволяет вратарю ограничить число соединений, устанавливаемых на исходящей линии, что, в свою очередь, служит для обеспечения необходимого качества обслуживания.

      Теперь ПК устанавливает TCP-соединение с вратарем, чтобы осуществить телефонный звонок. При установлении телефонного соединения используются традиционные протоколы телефонной сети, ориентированные на соединение. Поэтому требуется протокол TCP. С другой стороны, в телефонной системе нет никаких RAS, которые позволяли бы телефонным аппаратам заявлять о своем присутствии, поэтому разработчики Н.323 могли применять как UDP, так и TCP.

      SIP от IETF

      SIP (Session Initiation Protocol) - протокол установления сессии. Протокол оговаривает способ установки телефонных соединений через Интернет, технологию организации систем для видеоконференций и способы создания других мультимедийных приложений.

      В отличие от Н.323, представляющего собой целый набор протоколов, SIP — это единый модуль, способный взаимодействовать с разнообразными интернет-приложениями. Например, номера телефонов определяются в виде URL, то есть на веб-страницах можно размещать гиперссылки, щелкнув на которых, пользователь сможет установить телефонное соединение (примерно так же схема mailto позволяет написать электронное письмо и отправить его по указанному в ссылке адресу).

      Протокол SIP

      • описывает порядок установления соединения с удалённым клиентом;
      • согласовывает открытие дополнительных каналов обмена на основе других протоколов (например, RTP);
      • допускает добавление или удаление таких каналов в течение сеанса (конференц-связь).
      Схема работы по протоколу SIP

      Схема работы по протоколу SIP

      Протокол SIP позволяет устанавливать и двухсторонние соединения (то есть обычные телефонные соединения), и многосторонние (когда каждый из участников может как слушать собеседников, так и говорить), и широковещательные (когда один из участников говорит, а остальные могут только слушать). Во время сеанса связи могут передаваться аудио-, видео- или другие данные. Эта возможность используется, например, при организации сетевых игр с большим количеством участников в реальном времени. SIP занимается только установкой, управлением и разрывом соединений. Для передачи данных используются другие протоколы, например, RTP/RTCP.

      Телефонные номера в SIP представляются в виде URL со схемой sip. Например, sip:ilse@cs.university.edu свяжет вас с пользователем по имени Use, хост которого определяется DNS -именем cs.university.edu. SIP URL могут содержать также адреса формата IPv4, IPv6 или реальные номера телефонов. Клиенты SIP традиционно используют порт 5060 TCP и UDP для соединения серверов и других элементов SIP.

      Протокол SIP является текстовым, он построен по модели HTTP. Одна из сторон посылает ASCII-сообщение, в котором первая строка содержит имя метода, а ниже следуют дополнительные строки, содержащие заголовки для передачи параметров. Многие заголовки взяты из стандарта MIME, что позволяет SIP взаимодействовать с существующими интернет- приложениями.

      Методы

      INVITE Запрос запуска сеанса связи
      АС K Подтверждение запуска сеанса
      BYE Запрос окончания сеанса
      OPTIONS Опрос возможностей хоста
      CANCEL Отмена запроса
      REGISTER Информирование сервера переадресации о текущем местоположении пользователя

      Skype

      Историческая справка. Компания Skype

      Компания Skype основана Никласом Ценнштрём и Янусом Фриисом в 2003 году.

      Программа Skype основана на P2P технологиях и обеспечивает:

      • бесплатную голосовую связь через Интернет между компьютерами;
      • платные услуги для связи с абонентами обычной телефонной сети;
      • видео конференции, обмен сообщениями и файлами.

      Skype — это бесплатное проприетарное программное обеспечение для VoIP, обеспечивающее бесплатную шифрованную голосовую связь через Интернет между компьютерами, а также платные услуги для связи с абонентами обычной телефонной сети.

      Архитектура сети Skype

      В отличие от многих других программ IP-телефонии, для передачи данных Skype использует P2P архитектуру. Каталог пользователей Skype распределён по компьютерам пользователей сети Skype, что позволяет сети легко масштабироваться до очень больших размеров (в данный момент более 100 миллионов пользователей, пять-десять миллионов онлайн) без дорогой инфраструктуры централизированных серверов. Однако, в процессе работы Skype генерирует типичный для P2P-сетей и неизбежный постоянный трафик, который может достигать 1 Гб в месяц. VoIP-протокол Skype закрыт и используется только оригинальным ПО Skype. При помощи API к его функциям могут получать доступ программы сторонних разработчиков.

      При установке соединения между ПК данные шифруются. Случаев расшифровки и/или перехвата Skype на 2008 год не зафиксировано, большинство спецслужб выражают по этому поводу недовольство.

      Одним из недостатков Skype считается использование проприетарного протокола, несовместимого с открытыми стандартами (такими, как SIP или H.323). Это приводит к тому, что сервис, основанный на этом протоколе, приносит доход только компании Skype.

      Архитектура сети Skype
      • сервер авторизации Skype;
      • обычные узлы (пользователи);
      • супер-узлы (имеют достаточно ресурсов и долго подключены к сети);
      • супер-узлы Skype.

      Транспортный уровень

      Функции транспортного уровня

      • обеспечивает логическое соединение между приложениями;
      • реализует надежную передачу данных;
      • обеспечивает контроль скорости передачи данных.

      Сокеты

      Сокет (socket, гнездо) — это структура данных, идентифицирующая сетевое соединение.

      Зачем нужны сокеты? Сервер (программа) может одновременно поддерживать несколько TCP-соединений с другими компьютерами, используя один и тот же стандартный номер порта. Как это реализовать? Можно возложить эту задачу на программиста. Пусть он выбирает из буфера приема сетевого уровня пакеты, смотрит от кого они отправлены и отвечает соответствующим образом. Но можно сделать все это удобнее.

      С каждым соединением должен быть связан свой поток, в который можно писать информацию и из которого можно ее считывать. Каждому потоку соответствует свой IP-адрес удаленного компьютера и свой порт удаленного компьютера. Будем назвать структуру данных, соответствующую каждому такому потоку, сокетом (розеткой). Таким образом, сервер можно сравнить с разветвителем с кучей розеток, к которым подключены клиенты.

      Если сделать так, то вместо того, чтобы разбираться в куче разносортных пакетов из буфера приема сетевого уровня, сервер будет читать из потоков, каждый из которых соответствует своему клиенту. Данные от клиентов не будут сваливаться в кучу, а будут распределяться по потокам-сокетам. Ответственность за такое распределение ложится не на программиста, а на драйвер транспортного уровня операционной системы.

      Сокеты были разработаны в университете Калифорнии в городе Berkeley, стали стандартом де-факто в противоположность OSI TLI (Transport Layer Interface).

      Историческая справка. Раскол UNIX

      С 1978 года начинает свою историю BSD UNIX, созданный в университете Беркли. Автором BSD был Билл Джой. В начале 1980-х компания AT&T, которой принадлежали Bell Labs, осознала ценность UNIX и начала создание коммерческой версии UNIX. Важной причиной раскола UNIX стала реализация в 1980 г. стека протоколов TCP/IP. До этого межмашинное взаимодействие в UNIX пребывало в зачаточном состоянии — наиболее существенным способом связи был UUCP (средство копирования файлов из одной UNIX-системы в другую, изначально работавшее по телефонным сетям с помощью модемов).

      Эти две операционные системы реализовали 2 различных интерфейса программирования сетевых приложений: Berkley sockets (TCP/IP) и интерфейс транспортного уровня TLI (OSI ISO) (англ. Transport Layer Interface). Интерфейс Berkley sockets был разработан в университете Беркли и использовал стек протоколов TCP/IP, разработанный там же. TLI был создан AT&T в соответствии с определением транспортного уровня модели OSI. Первоначально в ней не было реализации TCP/IP или других сетевых протоколов, но подобные реализации предоставлялись сторонними фирмами. Это, как и другие соображения (по большей части, рыночные), вызвало окончательное размежевание между двумя ветвями UNIX — BSD (университета Беркли) и System V (коммерческая версия от AT&T). Впоследствии многие компании, лицензировав System V у AT&T, разработали собственные коммерческие разновидности UNIX, такие, как AIX, HP-UX, IRIX, Solaris.

      Примитивы сокетов
      SOCKET создать новый (пустой) сокет
      BIND сервер связывает свой локальный адрес (порт) с сокетом
      LISTEN сервер выделяет память под очередь подсоединений клиентов (TCP)
      ACCEPT сервер ожидает подсоединения клиента или принимает первое подключение из очереди (TCP). Чтобы заблокировать ожидание входящих соединений, сервер выполняет примитив ACCEPT. Получив запрос соединения, транспортный модуль ОС создает новый сокет с теми же свойствами, что и у исходного сокета, и возвращает описатель файла для него. После этого сервер может разветвить процесс или поток, чтобы обработать соединение для нового сокета и параллельно ожидать следующего соединения для оригинального сокета
      CONNECT клиент запрашивает соединение (TCP)
      SEND/SEND_TO послать данные (TCP/UDP)
      RECEIVE/RECEIVE_FROM получить данные (TCP/UDP)
      DISCONNECT запросить разъединение (TCP)

      Мультиплексирование и демультиплексирование

      Мультиплексирование — сбор сообщений от сокетов всех приложений и добавление заголовков.

      Демультиплексирование — распределение приходящих данных по сокетам.

      Для UDP нужный сокет определяется номером порта получателя, для TCP — номером порта получателя, IP-адресом и номером порта отправителя.

      Протоколы транспортного уровня

      На транспортном уровне действует два протокола: TCP (надежный) и UDP (ненадежный).

      Протокол UDP

      UDP (User Datagram Protocol) выполняет минимум действий, позволяя приложению почти напрямую работать с сетевым уровнем. Работает гораздо быстрее TCP, потому что не нужно устанавливать соединение и ожидать подтверждения доставки. Возможны потери сегментов. Осуществляет контроль корректности передаваемых данных (контрольная сумма).

      Структура UDP-сегмента

      Заголовок всего 8 байт.

      Принципы надежной передачи данных

      Спроектируем протокол myTCP, последовательно его усложняя.

        Состояния протокола myTCP 1.0. Передача по абсолютно надежному каналу

      Ошибка создания миниатюры: Файл не найден
      Отправитель
      Ошибка создания миниатюры: Файл не найден
      Получатель

        Состояния протокола myTCP 2.0. Передача по каналу, допускающему искажения битов. Потери пакетов невозможны

      Ошибка создания миниатюры: Файл не найден
      Отправитель
      Ошибка создания миниатюры: Файл не найден
      Получатель

      Но квитанции тоже могут теряться. Если квитанция искажена отправитель опять посылает пакет. Получатель должен думать как обрабатывать повторные пакеты (нужно ввести новое состояние — передали прошлый пакет приложению или нет).

      Роль идентификаторов «повторный» и «новый» в TCP/IP играют номера пакетов (т.к. пакеты еще могут теряться).

        Состояния протокола myTCP 2.1. Передача по каналу, допускающему искажения битов. Потери пакетов невозможны

      Ошибка создания миниатюры: Файл не найден
      Отправитель
      Ошибка создания миниатюры: Файл не найден
      Получатель

      Главная разница между состояниями получателя в том, как обрабатываются повторные пакеты. В состоянии «Прошлый пакет передан приложению» мы выкидываем повторные пакеты, а в состоянии «Прошлый пакет не был передан приложению» мы их принимаем и передаем приложению.

      Теперь пришло время вспомнить, что пакеты могут теряться.

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

      Таким образом, мы приходим к необходимости таймера. В случае, если прошло какое-либо определенное время и подтверждение не пришло, то осуществляется повторная отправка сообщения. Интервал времени — маленький т.к. вероятность потери принимается близкой к 1 (это и вправду так даже для хорошего WiFi-соединения).

      Недостатки протоколов с ожиданием подтверждений

      Рассмотрим пример. Пусть имеется 1Гб-канал Ростов — Москва. Посчитаем время отправки 1000 байт (или 8000 бит):

      8000 бит / 1 Гб/с = 8 мкс

      Время распространения сигнала:

      1000 км / 300 000 км/с = 3333 мкс

      Итого: следующие 1000 байт будут отправлены более чем через 6674 мкс

      Вывод: 99,9% времени канал не использует.

      Путь решения — увеличить размер пакета. Но ведь если хотя бы 1 бит исказится, то весь пакет выкинут. Что тогда?

      Протоколы скользящего окна

      Решение проблемы: разрешить отправителю посылать не один кадр, а несколько прежде чем остановиться и перейти в режим ожидания подтверждений (квитанций). Такая техника называется конвейерной обработкой.

      На рисунке зеленым обозначены те квитанции, которые уже получены, желтым — отправленные, но не полученные, голубые подготовлены к отправке, а белые нельзя отправлять, пока не получим квитанции на желтые. Окно: желтые и голубые — это пакеты, которые могут быть переданы без ожидания квитанций. Первый белый пакет может быть отправлен только после того, как получили подтверждение на первый желтый. Тогда окно подвигается на 1 вправо.

      Может возникнуть вопрос: зачем ограничивать размер окна, давайте все пакеты передадим, а потом будем ожидать подтверждений. Но так делать нельзя: легко получить перегрузку в сети.

      Есть два способа решить проблемы возникновения ошибок при конвейеризации кадров:

      • GBN (Go Back N — возвращение на N пакетов назад);
      • SR (Selective Repeat — выборочное повторение).
      GBN

      Получатель отправляет только положительные квитанции и только о получении тех пакетов, для которых выполняется условие: все пакеты с меньшими номерами уже получены. Таким образом, здесь используется групповое квитирование: получение отправителем квитанции с номером i означает, что все пакеты до i включительно доставлены успешно. Если по истечении некоторого времени отправитель не получает квитанции, он повторяет отправление всех N пакетов начиная со следующего за последним квитированным.

      Метод GBN неэффективен при большом окне и долгом распространении пакетов по сети, в которой случаются потери. Пример: отправили 1000 пакетов, второй не пришел, приходится повторять отправку всех, начиная со второго. Мы «засоряем» сеть бесполезным трафиком.

      SR

      Этот подход предусматривает отправку квитанции на каждый пакет. Получатель хранит в своем буфере все правильные кадры, принятые после неверного или потерянного. При этом неверный кадр отбрасывается. Если время ожидания квитанции на какой-то кадр истекает, отправитель еще раз отправляет этот кадр, не повторяя отправку всех последующих. Если вторая попытка будет успешной, накопившиеся у получателя пакеты могут быть переданы на сетевой уровень, после чего будет выслано подтверждение получения кадра с наибольшим номером.

      Часто выборочный метод комбинируют с отправкой получателем «отрицательного подтверждения» (NAK — Negative Acknowledgement) при обнаружении ошибки (например, при неверной контрольной сумме). При этом эффективность работы повышается.

      При большом окне подход SR может потребовать значительного размера буфера.

      Формат TCP-сегмента

      Протокол TCP
      Формат TCP-сегмента

      TCP-сегмент состоит из поля данных и нескольких полей заголовка. Поле данных содержит фрагмент данных, передаваемых между процессами. Размер поля данных ограничивается величиной MSS (максимальный размер сегмента). Когда протокол осуществляет передачу большого файла, он, как правило, разбивает данные на фрагменты размером MSS (кроме последнего фрагмента, который обычно имеет меньший размер). Интерактивные приложения, напротив, часто обмениваются данными, объем которых значительно меньше MSS. Например, приложения удаленного доступа к сети, подобные Telnet, могут передать транспортному уровню 1 байт данных. Поскольку обычно длина заголовка ТСР-сегмента составляет 20 байт (что на 12 байт больше, чем в UDP), полный размер сегмента в этом случае равен 21 байт.

      Как и в протоколе UDP, заголовок включает номера портов отправителя и получателя, предназначенные для процедур мультиплексирования и демультиплексирования данных, а также поле контрольной суммы. Кроме того, в состав TCP-сегмента входят еще некоторые поля.

      • 32-разрядные поля порядкового номера и номера подтверждения. Необходимы для надежной передачи данных.
      • 4-разрядное поле длины заголовка определяет длину TCP-заголовка в 32-разрядных словах. Минимальный размер составляет 5 слов, а максимальный — 15, что составляет 20 и 60 байт соответственно. TCP-заголовок может иметь переменную длину благодаря полю параметров, описанному ниже (как правило, поле параметров является пустым; это означает, что длина заголовка составляет 20 байт).
      • Поле флагов состоит из 6 бит. Бит подтверждения (АСК) указывает на то, что значение, содержащееся в квитанции, является корректным. Биты RST, SYN и FIN используются для установки и завершения соединения. Установленный бит PSH инструктирует получателя протолкнуть данные, накопившиеся в приемном буфере, в приложение пользователя. Бит URG показывает, что в сегменте находятся данные, помещенные верхним уровнем как «срочные». Расположение последнего байта срочных данных указано в 16-разрядном поле указателя срочных данных. На принимающей стороне протокол TCP должен уведомить верхний уровень о наличии срочных данных в сегменте и передать ему указатель на конец этих данных. На практике флаги PSH, URG и поле указателя срочных данных не используются. Мы упомянули о них лишь для полноты описания.
      • 16-разрядное окно приема используется для управления потоком данных. Оно содержит количество байтов, которое способна принять принимающая сторона.
      • Указатель важности — 16-битовое значение положительного смещения от порядкового номера в данном сегменте. Это поле указывает порядковый номер октета которым заканчиваются важные (urgent) данные. Поле принимается во внимание только для пакетов с установленным флагом URG.
      • Необязательное поле параметров используется в случаях, когда передающая и принимающая стороны «договариваются» о максимальном размере сегмента, либо для масштабирования окна в высокоскоростных сетях. Также в этом поле определяется параметр временных меток. Дополнительную информацию можно найти в документах RFC 854 и RFC 1323.
      Порядковые номера и номера подтверждения

      Порядковые номера и номера подтверждения.JPG

      Порядковый номер сегмента — это номер первого байта этого сегмента.

      Номер подтверждения — это порядковый номер следующего ожидаемого байта.

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

      Протокол TCP рассматривает данные как неструктурированный упорядоченный поток байтов. Такой подход проявляется в том, что TCP назначает порядковые номера не сегментам, а каждому передаваемому байту. Исходя из этого, порядковый номер сегмента определяется как порядковый номер первого байта этого сегмента. Рассмотрим следующий пример. Пусть хост А желает переслать поток данных хосту В через TCP-соединение. Протокол TCP на передающей стороне неявно нумерует каждый байт потока. Пусть размер передаваемого файла составляет 500 000 байт, величина MSS равна 1000 байт, и первый байт потока имеет порядковый номер 0. TCP разбивает поток данных на 500 сегментов. Первому сегменту присваивается порядковый номер 0, второму сегменту — номер 1000, третьему сегменту — номер 2000, и т. д. Порядковые номера заносятся в поля порядковых номеров каждого TCP-сегмента.

      Теперь рассмотрим номера подтверждения. Вспомним о том, что протокол TCP обеспечивает дуплексную передачу данных, то есть через единственное TCP-соединение данные между хостами А и В могут передаваться одновременно в обе стороны. Каждый сегмент, исходящий из хоста В, содержит порядковый номер данных, передающихся от хоста В к хосту А. Номер подтверждения, который хост А помещает в свой сегмент, — это порядковый номер следующего байта, ожидаемого хостом А от хоста В. Рассмотрим следующий пример. Предположим, что хост А получил все байты с номерами от 0 до 535, посланные хостом В, и формирует сегмент для передачи хосту В. Хост А ожидает, что следующие байты, посылаемые хостом В, будут иметь номера, начинающиеся с 536, и помещает число 536 в поле номера подтверждения своего сегмента.

      Рассмотрим другую ситуацию. Пусть хост А получил от хоста В два сегмента, в первом из которых содержатся байты с номерами от 0 до 535, а во втором — байты с номерами от 900 до 1000. Это означает, что по какой-либо причине байты с номерами от 536 до 899 не были получены хостом А. В этом случае хост А ожидает появления отсутствующих байтов и в поле номера подтверждения своего сегмента помещает число 536. Поскольку TCP квитирует принятые данные до первого отсутствующего байта, говорят, что он поддерживает общее квитирование.

      Последний пример демонстрирует очень важный аспект функционирования протокола TCP. Третий сегмент (содержащий байты 900-1000) принят хостом А раньше, чем второй (содержащий байты 536-899), то есть с нарушением порядка следования данных. Возникает вопрос: как протокол TCP реагирует на нарушение порядка? Если полученный сегмент содержит номер последовательности больший, чем ожидаемый, то данные из сегмента буферизируется, но номер подтвержденной последовательности не изменяется. Если в последствии будет принят сегмент, относящийся к ожидаемому номеру последовательности, то порядок данных будет автоматически восстановлен исходя из номеров последовательностей в сегментах. Таким образом TCP относится к протоколам SR, но у него используется общее квитирование как в GBN. Хотя SR – не совсем чистое. Если посылаемая сторона получает несколько (3) отрицательных квитанций на один и тот же сегмент x, то она догадывается, что произошла перегрузка сети и сегменты x+1, x+2, x+3,… тоже не были доставлены. Тогда посылается вся серия начиная с x – как в протоколах GBN.

      Проблемы с максимальным размером сегмента

      TCP требует явного указания максимального размера сегмента в случае если виртуальное соединение осуществляется через сегмент сети, где максимальный размер блока (MTU) менее чем стандартный MTU Ethernet (1500 байт). В протоколах туннелирования, таких как GRE, IPIP, а так же PPPoE MTU туннеля меньше чем стандартный, поэтому сегмент TCP максимального размера имеет длину пакета больше, чем MTU. Поскольку фрагментация в подавляющем большинстве случаев запрещена, то такие пакеты отбрасываются.

      Проявление этой проблемы выглядит как «зависание» соединений. При этом «зависание» может происходить в произвольные моменты времени, а именно тогда, когда отправитель использовал сегменты длиннее допустимого размера. Для решения этой проблемы на маршрутизаторах применяются правила Firewall-а, добавляющие параметр MSS во все пакеты, инициирующие соединения, чтобы отправитель использовал сегменты допустимого размера. MSS может так же управляться параметрами операционной системы.

      Установка TCP-соединения

      Тройное рукопожатие

      Чтобы установить соединение, хост 2 пассивно ожидает входящего соединения, выполняя примитив ACCEPT.

      Хост 2 выполняет примитив CONNECT, указывая IP-адрес и порт, с которым он хочет установить соединение, максимальный размер TCP-сегмента и т.п.. Примитив CONNECT посылает TCP-сегмент «Connection request» с установленным битом SYN=1 и сброшенным битом АСК=0 и ждет ответа. Таким образом, хост 1 сообщает порядковый номер x последовательности битов от хоста 1 к 2.

      Хост 2 отсылает в ответ подтверждение «Connection accepted» (функция accept). Последовательность TCP-сегментов, посылаемых в нормальном случае, показана на рис: SYN=1 ASK=1, хост 2 сообщает порядковый номер x последовательности битов от хоста 2 к 1 и сообщает, что он ожидает продолжения данных начиная с байта № x+1.

      Хост 1 (Connect) отправляет подтверждение о получении согласия на установление соединения.

      Борьба с перегрузкой в TCP

      Когда в какую-либо сеть поступает больше данных, чем она способна обработать, в сети образуются заторы. Интернет в этом смысле не является исключением. Хотя сетевой уровень также пытается бороться с перегрузкой, основной вклад в решение этой проблемы, заключающееся в снижении скорости передачи данных, осуществляется протоколом TCP.

      Теоретически, с перегрузкой можно бороться с помощью принципа, заимствованного из физики, — закона сохранения пакетов. Идея состоит в том, чтобы не передавать в сеть новые пакеты, пока ее не покинут (то есть не будут доставлены) старые. Протокол TCP пытается достичь этой цели с помощью динамического управления размером окна.

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

      В настоящее время потери пакетов при передаче случаются относительно редко, так как большинство междугородных линий связи являются оптоволоконными (хотя в беспроводных сетях процент пакетов, теряемых из-за помех, довольно высок). Соответственно, большинство потерянных пакетов в Интернете вызвано заторами. Все TCP-алгоритмы Интернета предполагают, что потери пакетов вызываются перегрузкой сети, и следят за тайм-аутами как за предвестниками проблем.

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

      Борьба с перегрузкой в TCP

      Проиллюстрируем эту проблему на примере водопровода. На рисунке а мы видим толстую трубу, ведущую к получателю с небольшой емкостью. До тех пор, пока отправитель не посылает воды больше, чем может поместиться в ведро, вода не будет проливаться, на рисунке б ограничительным фактором является не емкость ведра, а пропускная способность сети. Если из крана в воронку вода будет литься слишком быстро, то уровень воды в воронке начнет подниматься и, в конце концов, часть воды может перелиться через край воронки.

      Решение, применяемое в Интернете, состоит в признании существования двух потенциальных проблем: низкой пропускной способности сети и низкой емкости получателя — и в раздельном решении обеих проблем. Для этого у каждого отправителя есть два окна: окно, предоставленное получателем, и окно перегрузки. Размер каждого из них соответствует количеству байтов, которое отправитель имеет право передать. Отправитель руководствуется минимальным из этих двух значений. Например, получатель говорит: «Посылайте 8 Кбайт», но отправитель знает, что если он пошлет более 4 Кбайт, то в сети образуется затор, поэтому он посылает все же 4 Кбайт. Если же отправитель знает, что сеть способна пропустить и большее количество данных, например 32 Кбайт, он передаст столько, сколько просит получатель (то есть 8 Кбайт).

      При установке соединения отправитель устанавливает размер окна перегрузки равным размеру максимального используемого в данном соединении сегмента. Затем он передает один максимальный сегмент. Если подтверждение получения этого сегмента прибывает прежде, чем истекает период ожидания, к размеру окна добавляется размер сегмента, то есть размер окна перегрузки удваивается, и посылаются уже два сегмента. В ответ на подтверждение получения каждого из сегментов производится расширение окна перегрузки на величину одного максимального сегмента. Допустим, размер окна равен n сегментам. Если подтверждения для всех сегментов приходят вовремя, окно увеличивается на число байтов, соответствующее n сегментам. По сути, подтверждение каждой последовательности сегментов приводит к удвоению окна перегрузки.

      Этот процесс экспоненциального роста продолжается до тех пор, пока не будет достигнут размер окна получателя или не будет выработан признак тайм-аута, сигнализирующий о перегрузке в сети. Например, если пакеты размером 1024, 2048 и 4096 байт дошли до получателя успешно, а в ответ на передачу пакета размером 8192 байта подтверждение не пришло в установленный срок, окно перегрузки устанавливается равным 4096 байтам. Пока размер окна перегрузки остается равным 4096 байтам, более длинные пакеты не посылаются, независимо от размера окна, предоставляемого получателем. Этот алгоритм называется затяжным пуском, или медленным пуском. Однако он не такой уж и медленный (Jacobson, 1988). Он экспоненциальный. Все реализации протокола TCP обязаны его поддерживать.

      Рассмотрим теперь механизм борьбы с перегрузкой, применяемый в Интернете. Помимо окон получателя и перегрузки, в качестве третьего параметра в нем используется пороговое значение, которое изначально устанавливается равным 64 Кбайт. Когда возникает ситуация тайм-аута (подтверждение не возвращается в срок), новое значение порога устанавливается равным половине текущего размера окна перегрузки, а окно перегрузки уменьшается до размера одного максимального сегмента. Затем, так же как и в предыдущем случае, используется алгоритм затяжного пуска, позволяющий быстро обнаружить предел пропускной способности сети. Однако на этот раз экспоненциальный рост размера окна останавливается по достижении им порогового значения, после чего окно увеличивается линейно, на один сегмент для каждой следующей передачи. В сущности, предполагается, что можно спокойно урезать вдвое размер окна перегрузки, после чего постепенно наращивать его.

      Механизмы надежной передачи. Обобщение

      Контрольная сумма Обнаружение искажений битов в принятом пакете
      Таймер Отсчет интервала ожидания и указание на его истечение. Последнее означает, что с высокой степенью вероятности пакет или его квитанция потеряны при передаче. В случае, если пакет доставляется с задержкой, но не теряется (преждевременное истечение интервала ожидания), либо происходит потеря квитанции, повторная передача приводит кдублированию пакета на принимающей стороне
      Порядковые номера Последовательная нумерация пакетов, посылаемых передающей стороной. «Пробелы» в номерах получаемых пакетов позволяют сделать заключение о потерях данных. Одинаковые порядковые номера пакетов означают, что пакеты дублируют друг друга
      «+» и «-» квитанции Генерируется принимающей стороной и указывает передающей стороне на то, что соответствующий пакет или группа пакетов были или не были приняты. Обычно подтверждение содержит порядковые номера успешно принятых пакетов. В зависимости от протокола различают индивидуальные и групповые подтверждения
      Окно/конвейер Ограничивают диапазон порядковых номеров, которые могут использоваться для передачи пакетов. Групповая передача и квитирование позволяют значительно увеличить пропускную способность протоколов по сравнению с режимом ожидания подтверждений. Размер окна может быть рассчитан на основе возможностей приема и буферизации принимающей стороны, а также уровня загрузки сети

      Особенности программирования

      1. Потоковое соединение TCP
        • ситуация а) возможна при плохой связи, если промежуток времени между приходами групп дейтаграмм сетевого уровня велик:
          • компьютер1 один раз использует функцию send;
          • компьютер2 не получает всю информацию за один вызов recv (нужно несколько вызовов).
        • ситуация б) возможна, если интервал времени между вызовами функции send мал и размер данных мал:
          • компьютер1 использует функцию send несколько раз;
          • компьютер2 получает всю информацию за один вызов recv.
      2. По протоколу UDP
        • ситуация а) - невозможна
          • компьютер1 один раз использует функцию send, на сетевом уровне UDP-сегмент разбивается на несколько пакетов;
          • компьютер2 получает сегмент всегда одним вызовом recv и только, если пришли все IP-дейтаграммы.
        • ситуация б) - невозможна
          • разные вызовы функции sendto на компьютере1 соответствуют разным UDP-датаграммам и разным вызовам recvfrom на компьютере2.
      3. Если буфер в функциях recv и recvfrom меньше, чем размер присланных данных, то в случае UDP часть данных теряется, а в случае TCP – остаток сохраняется для последующего вызова recv.
      4. У UDP-сервера 1 сокет, а TCP-сервер имеет много разных сокетов (по количеству одновременно подключенных клиентов) и каждому передается своя информация.

      Сетевой уровень

      Транспортный уровень предоставляет услуги связи между двумя процессами. Он опирается на функции сетевого уровня. Сетевой уровень передает данные от одного компьютера в сети к другому через цепочку промежуточных компьютеров. Пропуская через себя пакеты, промежуточные компьютеры не обращают внимания на заголовки прикладного и транспортного уровней. А вот информация, хранящаяся в заголовке сетевого уровня для них имеет большое значение. По этой информации они определяют по какому интерфейсу и кому передать пакет дальше.

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

      Основные составляющие

      • Протокол IP. Работает на всех компьютерах в цепочке передачи. На каждом решает кому отправить дальше (таблицы маршрутизации);
      • Протоколы маршрутизации. Позволяют динамически менять таблицы маршрутизации;
      • Иерархическая система адресации (IP-адреса).

      IP-адреса

      IP-адрес — это 4-байтовое число (32 разряда), например, 192.168.10.153. Он присваивается каждому интерфейсу. Примерами интерфейса являются сетевая карта, модем.

      Считается, что IP-адрес состоит из двух частей:

      • сетевая часть (номер подсети);
      • интерфейсная часть (номер интерфейса узла).

      IP-адреса образуют иерархическую систему адресации, которая позволяет определить местоположение. У оконечной системы может быть несколько IP-адресов (если несколько интерфейсов). Нет строгого разделения, где заканчивается сетевая часть и начинается интерфейсная.

      В случае изолированной сети её адрес может быть выбран администратором из специально зарезервированных для таких сетей блоков адресов (192.168.0.0/16, 172.16.0.0/12 или 10.0.0.0/8). Если же сеть должна работать как составная часть Интернета, то адрес сети выдаётся провайдером либо региональным интернет-регистратором (Regional Internet Registry, RIR). Существует пять RIR:

      • ARIN, обслуживающий Северную Америку;
      • APNIC, обслуживающий страны Юго-Восточной Азии;
      • AfriNIC, обслуживающий страны Африки;
      • LACNIC, обслуживающий страны Южной Америки и бассейна Карибского моря;
      • RIPE NCC, обслуживающий Европу, Центральную Азию, Ближний Восток.

      Региональные регистраторы получают номера автономных систем и большие блоки адресов у IANA, а затем выдают номера автономных систем и блоки адресов меньшего размера локальным интернет-регистраторам (Local Internet Registries, LIR), обычно являющимся крупными провайдерами.

      Разделение сетей на классы

      Разделение IP-адресов на классы

      Нетрудно посчитать, что всего в пространстве адресов IP — 128 сетей по 16 777 216 адресов класса A, 16384 сети по 65536 адресов класса B и 2 097 152 сети по 256 адресов класса C, а также 268 435 456 адресов многоадресной рассылки и 134 317 728 зарезервированных адресов. С ростом сети Интернет эта система оказалась неэффективной и была вытеснена CIDR (бесклассовой адресацией). Такое разделение на классы устарело.

      Историческая справка.

      Before classes

      Originally, the 32-bit IPv4 address consisted simply of an 8-bit network number field (which specified the particular network a host was attached to), and a rest field, which gave the address of the host within that network. This format was chosen before the advent of local area networks (LANs), when there were only a few, large, networks such as the ARPANET. This resulted in a very low number (254) of possible independent networks, and very early on, as local area networks started to appear, it became obvious that this would not be enough.

      To remain compatible with the existing IP address space and the IP packet structure, the definition of IP addresses was changed in 1981 in RFC 791 to allow unicast addresses with three different sizes of the network number field (and the associated rest field), as specified in the table (см. рис.) The number of usable host addresses available is always 2N - 2 (where N is the number of bits used, and the subtraction of 2 adjusts for the use of the all-bits-zero host portion for network address and the all-bits-one host portion as a broadcast address. Thus, for a Class C address with 8 bits available in the host field, the number of hosts is 254. The expanded network number field allowed a larger number of networks, thereby accommodating the continued growth of the Internet. The IP address netmask, which is commonly associated with an IPv4 address today, was not required because the mask was implicitly derived from the IP address itself. Any network device would inspect the first few bits of the IP address to determine the class of the address. The method of comparing the network numbers of two IP addresses did not change (see subnet). For each address, the network number field size and its subsequent value were determined (the rest field was ignored). The network numbers were then compared. If they matched, then the two addresses were on the same network.

      The replacement of classes

      The first design changes extended the addressing capability in the Internet, but did not prevent IP address shortage. The principal problem was that too many sites were too big for a Class C network number, and therefore received a Class B block. With the rapid growth of the Internet, the available pool of Class B addresses (214, or about 16,000 total) was rapidly being depleted. Classful networking was replaced by Classless Inter-Domain Routing (CIDR), starting in about 1993, to attempt to solve this problem. Early allocations of IP addresses by IANA were in some cases not made very efficiently, which contributed to the problem. (However, the commonly held notion that some American organizations unfairly or unnecessarily received Class A networks is wrong; most such allocations date to the period before the introduction of address classes, when the only address blocks available were what later became known as Class A networks.)

      Бесклассовая адресация

      Бесклассовая адресация

      Проблема нехватки IP-адресов решилась предоставлением сети возможности разделения на несколько частей. Например, вместо одного адреса класса В с 14 битами для номера сети и 16 битами для номера хоста было предложено использовать несколько другой формат — формировать адрес подсети из нескольких битов. Например, если в университете существует 35 подразделений, то 6-битным номером можно кодировать подсети, а 10-битным — номера хостов. С помощью такой адресации можно организовать до 64 сетей по 1022 хоста в каждой (адреса 0 и 1 не используются, как уже говорилось, поэтому не 1024 , а именно 1022 хоста).

      Иерархия IP-адресов

      Иерархия IP-адресов.JPG

      Зарезервированные адреса

      127.0.0.0 / 8 – петля обратной связи.

      10.0.0.0 / 8 и 192.168.0.0 / 16 – частные сети, подсоединенные к Интернету через NAT.

      Пример

      rigth

      На рисунке NAT нет. Изображено всего 7 сетей: 3 (между маршрутизаторами) (192.168.2.0, 192.168.3.0 и 192.168.1.0) + 4 (172.17.0.0, 10.0.0.0, 172.16.0.0, 192.168.4.0).

      Таблица маршрутизации. Результат команды route print

      Чтобы понять, как функционируют подсети, следует рассмотреть процесс обработки IP-пакетов маршрутизатором. У каждого маршрутизатора есть таблица,содержащая IP-адреса сетей (вида ) и IP-адреса хостов (вида ). Адреса сетей позволяют получать доступ к удаленным сетям, а адреса хостов — обращаться к локальным хостам. С каждой таблицей связан сетевой интерфейс, применяющийся для получения доступа к пункту назначения, а также другая информация. Когда IP-пакет прибывает на маршрутизатор, адрес получателя, указанный в пакете, ищется в таблице маршрутизации. Если пакет направляется в удаленную сеть, он пересылается следующему маршрутизатору по интерфейсу, указанному в таблице. Если пакет предназначен локальному хосту (например, в локальной сети маршрутизатора), он посылается напрямую адресату. Если номера сети, в которую посылается пакет, в таблице маршрутизатора нет, пакет пересылается маршрутизатору по умолчанию, с более подробными таблицами. Такой алгоритм означает, что каждый маршрутизатор должен учитывать только другие сети и локальные хосты, а не пары , что значительно уменьшает размер таблиц маршрутизатора.

      Формат IP-дейтаграммы

      Формат IP-дейтаграммы

      IP-дейтаграмма состоит из заголовка и текстовой части. Заголовок содержит обязательную 20-байтную часть, а также необязательную часть переменной длины. Формат заголовка показан на рисунке. Поле Версия содержит версию протокола, к которому принадлежит дейтаграмма. Включение версии в каждую дейтаграмму позволяет использовать разные версии протокола на разных машинах. Дело в том, что с годами протокол изменялся, и на одних машинах сейчас работают новые версии, тогда как на других продолжают использоваться старые. Сейчас происходит переход от версии IPv4 к версии IPv6. Он длится уже много лет, и не похоже, что скоро завершится. Длина заголовка является переменной величиной, для хранения которой выделено поле IHL (информация в нем представлена в виде 32-разрядных слов). Минимальное значение длины (при отсутствии необязательного поля) равно 5. Максимальное значение этого 4-битового поля равно 15, что соответствует заголовку длиной 60 байт; таким образом, максимальный размер необязательного поля равен 40 байтам. Для некоторых приложений, например, для записи маршрута, по которому должен быть переслан пакет, 40 байт слишком мало. В данном случае дополнительное поле оказывается бесполезным.

      Поле Тип службы — единственное поле, смысл которого с годами несколько изменился. Оно было (впрочем, и до сих пор) предназначено для различения классов обслуживания. Возможны разные комбинации надежности и скорости. Для оцифрованного голоса скорость доставки важнее точности. При передаче файла, наоборот, передача без ошибок важнее быстрой доставки. Изначально 6-разрядное поле Тип службы состояло из трехразрядного поля Precedence и трех флагов — D, Т и R. Поле Precedence указывало приоритет, от 0 (нормальный) до 7 (управляющий сетевой пакет). Три флаговых бита позволяли хосту указать, что беспокоит его сильнее всего, выбрав из набора (Задержка, Пропускная способность, Надежность). Теоретически, эти поля позволяют маршрутизаторам выбрать, например, между спутниковой линией с высокой пропускной способностью и большой задержкой и выделенной линией с низкой пропускной способностью и небольшой задержкой. На практике сегодняшние маршрутизаторы часто вообще игнорируют поле Тип службы. Поле Полная длина содержит длину всей дейтаграммы, включая как заголовок, так и данные. Максимальная длина дейтаграммы 65 535 байт. В настоящий момент этот верхний предел достаточен, однако с появлением гигабитных сетей могут понадобиться дейтаграммы большего размера. (когда Таненбаум это писал, гигабитных сетей еще не было) Поле Идентификатор позволяет хосту-получателю определить, какой дейта- грамме принадлежат полученные им фрагменты. Все фрагменты одной дейтаграммы содержат одно и то же значение идентификатора. Следом идет один неиспользуемый бит и два однобитных поля. Бит DF означает Don't Fragment (He фрагментировать). Это команда маршрутизатору, запрещающая ему фрагментировать дейтаграмму, так как получатель не сможет восстановить ее из фрагментов. Например, при загрузке компьютера его ПЗУ может запросить образ памяти в виде единой дейтаграммы. Пометив дейтаграмму битом DF, отправитель гарантирует, что дейтаграмма дойдет единым блоком, даже если для ее доставки придется избегать сетей с маленьким размером пакетов. От всех машин требуется способность принимать фрагменты размером 576 байт и менее.

      Бит MF означает More Fragments (Продолжение следует). Он устанавливается во всех фрагментах, кроме последнего. По этому биту получатель узнает о прибытии последнего фрагмента дейтаграммы. Поле Смещение фрагмента указывает положение фрагмента в исходной дейтаграмме. Длина всех фрагментов в байтах, кроме длины последнего фрагмента, должна быть кратна 8. Так как на это поле выделено 13 бит, максимальное количество фрагментов в дейтаграмме равно 8192, что дает максимальную длину дейтаграммы 65 536 байт, на 1 байт больше, чем может содержаться в поле Полная длина.

      Поле Время жизни (Число переходов) представляет собой счетчик, ограничивающий время жизни пакета. Предполагалось, что он будет отсчитывать время в секундах, таким образом, допуская максимальное время жизни пакета в 255 с. На каждом маршрутизаторе это значение должно было уменьшаться как минимум на единицу плюс время стояния в очереди. Однако на практике этот счетчик просто считает количество переходов через маршрутизаторы. Когда значение этого поля становится равным нулю, пакет отвергается, а отправителю отсылается пакет с предупреждением. Таким образом удается избежать вечного странствования пакетов, что может произойти, если таблицы маршрутизаторов по какой-либо причине испортятся.

      Собрав дейтаграмму из фрагментов, сетевой уровень должен решить, что с ней делать. Поле Протокол сообщит ему, какому процессу транспортного уровня ее передать. Это может быть TCP, UDP или что-нибудь еще. Нумерация процессов глобально стандартизирована по всему Интернету. Номера протоколов вместе с некоторыми другими были сведены в RFC 1700, однако теперь доступна интернет-версия в виде базы данных, расположенной по адресу www.iana.org. Поле Контрольная сумма заголовка защищает от ошибок только заголовок. Подобная контрольная сумма полезна для обнаружения ошибок, вызванных неисправными микросхемами памяти маршрутизаторов. Алгоритм вычисления суммы просто складывает все 16-разрядные полуслова в дополнительном коде, преобразуя результат также в дополнительный код. Таким образом, проверяемая получателем контрольная сумма заголовка (вместе с этим полем) должна быть равна нулю. Этот алгоритм надежнее, чем обычное суммирование. Обратите внимание на то, что значение Контрольной суммы заголовка должно подсчитываться заново на каждом транзитном участке, так как по крайней мере одно поле постоянно меняется (поле Время жизни). Для ускорения расчетов применяются некоторые хитрости.

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

      Служебные протоколы

      ICMP

      ICMP (Internet Control Message Protocol) — межсетевой протокол управляющих сообщений. Основная задача — передача информации об ошибках в дейтаграммах. Используется в программах ping (проверяет работает ли удаленный компьютер) и traceroute (определяет маршрут следования данных в сетях TCP/IP).

      Использование в traceroute

      Программа traceroute – определение маршрута до заданной оконечной системы. Принципы работы:

      1. На нужную оконечную систему отправляется серия дейтаграмм с разным временем жизни (1,2,3,…N; max=64). При получении устаревшей дейтаграммы маршрутизатор отвечает специальным ICMP сообщением.
      2. Программа запрашивает время между отправкой дейтаграммы и получением соответствующего ICMP сообщения. В ответ включается имя маршрутизатора.
      3. В итоге формируется список маршрутизаторов на основе ICMP – сообщений.

      Типы ICMP сообщений

      • ICMP сообщения (тип 12) генерируются при нахождении ошибок в заголовке IP пакета (за исключением самих ICMP пакетов, дабы не привести к бесконечно растущему потоку ICMP сообщений об ICMP сообщениях).
      • ICMP сообщения (тип 3) генерируются маршрутизатором при отсутствии маршрута к адресату.
      • Утилита ping, служащая для проверки возможности доставки IP пакетов использует ICMP сообщения с типом 8 (эхо-запрос) и 0 (эхо-ответ).
      • Утилита traceroute, отображающая путь следования IP пакетов, использует ICMP сообщения с типом 11.
      • ICMP сообщения с типом 5 используются маршрутизаторами для обновления записей в таблице маршрутизации отправителя.
      • ICMP сообщения с типом 4 используются получателем (или промежуточным маршрутизатором) для управления скоростью отправки сообщений отправителем.
      DHCP

      DHCP (Dynamic Host Configuration Protocol — протокол динамического конфигурирования узлов) позволяет компьютерам автоматически получать IP-адрес и другие параметры.

      DHCP — это сетевой протокол, позволяющий компьютерам автоматически получать IP-адрес и другие параметры, необходимые для работы в сети TCP/IP. Для этого компьютер обращается к специальному серверу, называемому сервером DHCP. Сетевой администратор может задать диапазон адресов, распределяемых среди компьютеров. Это позволяет избежать ручной настройки компьютеров сети и уменьшает количество ошибок. Протокол DHCP используется в большинстве крупных (и не очень) сетей TCP/IP.

      Протокол DHCP предоставляет три способа распределения IP-адресов:

      • Ручное распределение. При этом способе сетевой администратор сопоставляет аппаратному адресу (обычно MAC-адресу) каждого клиентского компьютера определённый IP-адрес. Фактически, данный способ распределения адресов отличается от ручной настройки каждого компьютера лишь тем, что сведения об адресах хранятся централизованно (на сервере DHCP), и потому их проще изменять при необходимости.
      • Автоматическое распределение. При данном способе каждому компьютеру на постоянное использование выделяется произвольный свободный IP-адрес из определённого администратором диапазона.
      • Динамическое распределение. Этот способ аналогичен автоматическому распределению, за исключением того, что адрес выдаётся компьютеру не на постоянное пользование, а на определённый срок. Это называется арендой адреса. По истечении срока аренды IP-адрес вновь считается свободным, и клиент обязан запросить новый (он, впрочем, может оказаться тем же самым).

      Некоторые реализации службы DHCP способны автоматически обновлять записи DNS, соответствующие клиентским компьютерам, при выделении им новых адресов.

      Принципы работы DHCP
      • Компьютер отправляет широковещательный UDP-пакет: «Кто может назначить мне IP-адрес?»
      • DHCP-серверы сети отправляют в ответ DHCP-предложения.
      • Клиент получает список предложений, выбирает нужное и отправляет DHCP-запрос на конкретный сервер.
      • От сервера приходит DHCP-подтверждение (в нем указывается IP-адрес, присвоенный клиенту).

      Решение проблемы нехватки IP-адресов (NAT)

      NAT (Network Address Translation — «преобразование сетевых адресов») — это механизм в сетях TCP/IP, позволяющий преобразовывать IP-адреса транзитных пакетов.

      Транзитными пакеты могут быть для коммуникационного оборудования (если вы настроили ваш ПК как роутер/гейт, то он также может считаться коммуникационным оборудованием). Задача коммуникаторов — доставлять по адресу приходящие пакеты. Пакеты, которые не предназначены самому коммуникатору, а должны быть перенаправлены и доставлены другому адресату можно уже назвать транзитными. Хотя есть еще один контекст этого понятия. Обычно коммуникаторы ставят на границе локальной и внешней сети. Если пакет пришел в один из портов коммуникатора из внешней сети, и должен быть перенаправлен в другой порт внешней сети, то его называют транзитным.

      Преобразование адресов методом NAT может производиться почти любым маршрутизирующим устройством — маршрутизатором, сервером доступа, межсетевым экраном. Суть механизма состоит в замене адреса источника (source) при прохождении пакета в одну сторону и обратной замене адреса назначения (destination) в ответном пакете. Наряду с адресами source/destination могут также заменяться номера портов source/destination.

      NAT выполняет две важных функции:

      • Позволяет сэкономить IP-адреса, транслируя несколько внутренних IP-адресов в один внешний публичный IP-адрес (или в несколько, но меньшим количеством, чем внутренних).
      • Позволяет предотвратить или ограничить обращение снаружи ко внутренним хостам, оставляя возможность обращения изнутри наружу.

      При инициации соединения изнутри сети создаётся трансляция. Ответные пакеты, поступающие снаружи, соответствуют созданной трансляции и поэтому пропускаются. Если для пакетов, поступающих снаружи, соответствующей трансляции не существует (а она может быть созданной при инициации соединения или статической), они не пропускаются.

      Недостатки
      • Не все протоколы могут «преодолеть» NAT. Некоторые не в состоянии работать, если на пути между взаимодействующими хостами есть трансляция адресов. Некоторые межсетевые экраны, осуществляющие трансляцию IP-адресов, могут исправить этот недостаток, соответствующим образом заменяя IP-адреса не только в заголовках IP, но и на более высоких уровнях (например, в командах протокола FTP). Из-за трансляции адресов «много в один» появляются дополнительные сложности с идентификацией пользователей и необходимость хранить полные логи трансляций.
      • DoS со стороны узла, осуществляющего NAT — если NAT используется для подключения многих пользователей к одному и тому же сервису, это может вызвать иллюзию DoS атаки на сервис (множество успешных и неуспешных попыток). Например, избыточное количество пользователей ICQ за NAT’ом приводит к проблеме подключения некоторых пользователей из-за превышения допустимой скорости коннектов к серверу. Частичным решением проблемы является использование пула адресов (группы адресов), для которых осуществляется трансляция.
      • Сложности в работе с пиринговыми сетями, в которых необходимо не только инициировать исходящие соединения, но также принимать входящие.

      Маршрутизация

      Маршрутизатор (устройство) получает пакет и должен отправить его дальше, но кому?

      Маршрутизация (англ. routing) — это процесс определения маршрута следования информации в сетях связи.

      Зачастую в его таблицах маршрутизации есть несколько записей для заданной в пакете сети назначения. Тогда маршрутизатор смотрит на значение метрики. Он выбирает маршрут с наименьшей метрикой. Метрика назначается для каждого сетевого интерфейса.

      В зависимости от того как вносятся изменения в таблицы маршрутов, маршрутизация называется статической или динамической. Существуют специальные протоколы, которые описывают правила согласования таблиц маршрутизации множества маршрутизаторов в какой-нибудь сети. Они называются протоколами маршрутизации.

      Протоколы обмена маршрутной информацией (протоколы маршрутизации) реализуют следующие типов алгоритмов:

      • дистанционно-векторный алгоритм (Distance Vector Algorithms, DVA);
      • алгоритм состояния связей (Link State Algorithms, LSA);
      • другие (например, гибридный протокол маршрутизации EIGRP от Cisco).
      Алгоритмы дистанционно-векторного типа

      В алгоритмах дистанционно-векторного типа каждый маршрутизатор периодически и широковещательно рассылает по сети вектор расстояний от себя до всех известных ему сетей. Под расстоянием обычно понимается число промежуточных маршрутизаторов через которые пакет должен пройти прежде, чем попадет в соответствующую сеть. Может использоваться и другая метрика, учитывающая не только число перевалочных пунктов, но и время прохождения пакетов по связи между соседними маршрутизаторами. Получив вектор от соседнего маршрутизатора, каждый маршрутизатор добавляет к нему информацию об известных ему других сетях, о которых он узнал непосредственно (если они подключены к его портам) или из аналогичных объявлений других маршрутизаторов, а затем снова рассылает новое значение вектора по сети. В конце-концов, каждый маршрутизатор узнает информацию об имеющихся в интерсети сетях и о расстоянии до них через соседние маршрутизаторы.

      Дистанционно-векторные алгоритмы хорошо работают только в небольших сетях. В больших сетях они засоряют линии связи интенсивным широковещательным трафиком, к тому же изменения конфигурации могут отрабатываться по этому алгоритму не всегда корректно, так как маршрутизаторы не имеют точного представления о топологии связей в сети, а располагают только обобщенной информацией — вектором дистанций, к тому же полученной через посредников. Работа маршрутизатора в соответствии с дистанционно-векторным протоколом напоминает работу моста, так как точной топологической картины сети такой маршрутизатор не имеет.

      Наиболее распространенным протоколом, основанным на дистанционно-векторном алгоритме, является протокол RIP.

      Алгоритмы состояния связей

      Алгоритмы состояния связей обеспечивают каждый маршрутизатор информацией, достаточной для построения точного графа связей сети. Все маршрутизаторы работают на основании одинаковых графов, что делает процесс маршрутизации более устойчивым к изменениям конфигурации. Широковещательная рассылка используется здесь только при изменениях состояния связей, что происходит в надежных сетях не так часто.

      Для того, чтобы понять, в каком состоянии находятся линии связи, подключенные к его портам, маршрутизатор периодически обменивается короткими пакетами со своими ближайшими соседями. Этот трафик также широковещательный, но он циркулирует только между соседями и поэтому не так засоряет сеть. Протоколом, основанным на алгоритме состояния связей, в стеке TCP/IP является протокол OSPF.

      Иерархическая маршрутизация

      Вся сеть разбивается на вложенные подсети. Внутри каждой автономной подсети используются протоколы внутренней маршрутизации. Автономные системы соединяются друг с другом с помощью шлюзов (gateway). Маршрутизация между этими шлюзами — внешняя маршрутизация. Все вместе это может быть также автономной подсетью.

      • внутренняя маршрутизация: RIP (Routing Internet Protocol) и OPSF (Open Shortest Path First);
      • внешняя маршрутизация: BGP (Border Gateway Protocol).

      При использовании иерархической маршрутизации маршрутизаторы разбиваются на отдельные, так называемые, регионы. Каждый маршрутизатор знает все детали выбора маршрутов в пределах своей области, но ему ничего не известно о внутреннем строении других регионов. При объединении нескольких сетей естественно рассматривать их как отдельные регионы, при этом маршрутизаторы одной сети освобождаются от необходимости знать топологию других сетей. В очень больших сетях двухуровневой иерархии может оказаться недостаточно. Может потребоваться группировать регионы в кластеры, кластеры в зоны, зоны в группы, и т. д., пока у нас не иссякнет фантазия на названия для новых образований.

      RIP

      Протокол RIP (Routing Information Protocol) — это один из наиболее распространенных протоколов маршрутизации в небольших компьютерных сетях, который позволяет маршрутизаторам динамически обновлять маршрутную информацию (направление и дальность в хопах), получая ее от соседних маршрутизаторов.

      Протокол RIP представляет собой один из старейших протоколов обмена маршрутной информацией, он до сих пор чрезвычайно распространен в вычислительных сетях.

      Историческая справка. Происхождение алгоритма маршрутизации RIP

      Алгоритм маршрутизации RIP (алгоритм Беллмана-Форда) был впервые разработан в 1969 г., как основной для сети ARPANET. Алгоритм Беллмана-Форда — это алгоритм поиска кратчайшего пути во взвешенном графе.

      В этом протоколе все сети имеют номера (способ образования номера зависит от используемого в сети протокола сетевого уровня), а все маршрутизаторы — идентификаторы. Протокол RIP широко использует понятие «вектор расстояний». Вектор расстояний представляет собой набор пар чисел, являющихся номерами сетей и расстояниями до них в хопах.

      Вектора расстояний итерационно распространяются маршрутизаторами по сети, и через несколько шагов каждый маршрутизатор имеет данные о достижимых для него сетях и о расстояниях до них. Если связь с какой-либо сетью обрывается, то маршрутизатор отмечает этот факт тем, что присваивает элементу вектора, соответствующему расстоянию до этой сети, максимально возможное значение, которое имеет специальный смысл — "связи нет". Таким значением в протоколе RIP является число 16.

      Таблица 1.
      Начальная информация в узле 2

      Сеть Расстояние Сосед
      A 1
      B 1
      C 1
      Таблица 2.
      Информация в узле 2 после двух шагов

      Сеть Расстояние Сосед
      A 1
      B 1
      C 1
      D 2 3
      E 2 5
      D 3 5
      F 3 5

      На рисунке цифрами обозначены маршрутизаторы. Каждый маршрутизатор хранит у себя вектор дистанций. Вектор дистанций — это таблица, где указаны IP-адреса сетей (первый столбец), расстояние до этих сетей в хопах (хоп — это количество ребер на графе) (второй столбец) и какому следующему маршрутизатору нужно отправить, чтобы пакет дошел до нужной сети. Буквами A, B, C, D, E, F обозначены сети между каждыми двумя маршрутизаторами.

      В таблице 1 приведена начальная информация, содержащаяся в топологической базе маршрутизатора 2, а в таблице 2 — информация в этой же базе после двух итераций обмена маршрутными пакетами протокола RIP. После определенного числа итераций маршрутизатор 2 будет знать о расстояниях до всех сетей интерсети, причем у него может быть несколько альтернативных вариантов отправки пакета к сети назначения.

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

      Для адаптации к изменению состояния связей и оборудования с каждой записью таблицы маршрутизации связан таймер. Если за время тайм-аута не придет новое сообщение, подтверждающее этот маршрут, то он удаляется из маршрутной таблицы.

      При использовании протокола RIP работает эвристический алгоритм динамического программирования Беллмана-Форда, и решение, найденное с его помощью является не оптимальным, а близким к оптимальному. Преимуществом протокола RIP является его вычислительная простота, а недостатками — увеличение трафика при периодической рассылке широковещательных пакетов и неоптимальность найденного маршрута.

      Неустойчивая работа при изменении конфигурации

      Неустойчивая работа при изменении конфигурации.JPG

      На рисунке показан случай неустойчивой работы сети по протоколу RIP при изменении конфигурации - отказе линии связи маршрутизатора M1 с сетью 1. При работоспособном состоянии этой связи в таблице маршрутов каждого маршрутизатора есть запись о сети с номером 1 и соответствующим расстоянием до нее.

      При обрыве связи с сетью 1 маршрутизатор М1 отмечает, что расстояние до этой сети приняло значение 16. Однако получив через некоторое время от маршрутизатора М2 маршрутное сообщение о том, что от него до сети 1 расстояние составляет 2 хопа, маршрутизатор М1 наращивает это расстояние на 1 и отмечает, что сеть 1 достижима через маршрутизатор 2. В результате пакет, предназначенный для сети 1, будет циркулировать между маршрутизаторами М1 и М2 до тех пор, пока не истечет время хранения записи о сети 1 в маршрутизаторе 2, и он не передаст эту информацию маршрутизатору М1.

      Для исключения подобных ситуаций маршрутная информация об известной маршрутизатору сети не передается тому маршрутизатору, от которого она пришла.

      OSPF

      Протокол OSPF (Open Shortest Path Firs) является достаточно современной реализацией алгоритма состояния связей (он принят в 1991 году) и обладает многими особенностями, ориентированными на применение в больших гетерогенных сетях.

      Протокол OSPF вычисляет маршруты в IP-сетях, сохраняя при этом другие протоколы обмена маршрутной информацией.

      Непосредственно связанные (то есть достижимые без использования промежуточных маршрутизаторов) маршрутизаторы называются соседями. Каждый маршрутизатор хранит информацию о том, в каком состоянии по его мнению находится сосед. Маршрутизатор полагается на соседние маршрутизаторы и передает им пакеты данных только в том случае, если он уверен, что они полностью работоспособны. Для выяснения состояния связей маршрутизаторы-соседи достаточно часто обмениваются короткими сообщениями HELLO.

      Для распространения по сети данных о состоянии связей маршрутизаторы обмениваются сообщениями другого типа. Эти сообщения называются router links advertisement — объявление о связях маршрутизатора (точнее, о состоянии связей). OSPF-маршрутизаторы обмениваются не только своими, но и чужими объявлениями о связях, получая в конце-концов информацию о состоянии всех связей сети. Эта информация и образует граф связей сети, который, естественно, один и тот же для всех маршрутизаторов сети.

      Кроме информации о соседях, маршрутизатор в своем объявлении перечисляет IP-подсети, с которыми он связан непосредственно, поэтому после получения информации о графе связей сети, вычисление маршрута до каждой сети производится непосредственно по этому графу по алгоритму Дэйкстры. Более точно, маршрутизатор вычисляет путь не до конкретной сети, а до маршрутизатора, к которому эта сеть подключена. Каждый маршрутизатор имеет уникальный идентификатор, который передается в объявлении о состояниях связей. Такой подход дает возможность не тратить IP-адреса на связи типа "точка-точка" между маршрутизаторами, к которым не подключены рабочие станции.

      Маршрутизатор вычисляет оптимальный маршрут до каждой адресуемой сети, но запоминает только первый промежуточный маршрутизатор из каждого маршрута. Таким образом, результатом вычислений оптимальных маршрутов является список строк, в которых указывается номер сети и идентификатор маршрутизатора, которому нужно переслать пакет для этой сети. Указанный список маршрутов и является маршрутной таблицей, но вычислен он на основании полной информации о графе связей сети, а не частичной информации, как в протоколе RIP.

      Протокол состояния связей OSPF.JPG

      Представим себе один день из жизни транзитной локальной сети. Пусть у нас имеется сеть Ethernet, в которой есть три маршрутизатора — Джон, Фред и Роб (имена членов рабочей группы Internet, разработавшей протокол OSPF). Эти маршрутизаторы связаны с сетями в других городах с помощью выделенных линий.

      Пусть произошло восстановление сетевого питания после сбоя. Маршрутизаторы и компьютеры перезагружаются и начинают работать по сети Ethernet. После того, как маршрутизаторы обнаруживают, что порты Ethernet работают нормально, они начинают генерировать сообщения HELLO, которые говорят о их присутствии в сети и их конфигурации. Однако маршрутизация пакетов начинает осуществляться не сразу — сначала маршрутизаторы должны синхронизировать свои маршрутные базы.

      На протяжении интервала отказа маршрутизаторы продолжают посылать сообщения HELLO. Когда какой-либо маршрутизатор посылает такое сообщение, другие его получают и отмечают, что в локальной сети есть другой маршрутизатор. Когда они посылают следующее HELLO, они перечисляют там и своего нового соседа. Когда период отказа маршрутизатора истекает, то маршрутизатор с наивысшим приоритетом и наибольшим идентификатором объявляет себя выделенным (а следующий за ним по приоритету маршрутизатор объявляет себя резервным выделенным маршрутизатором) и начинает синхронизировать свою базу данных с другими маршрутизаторами. С этого момента времени база данных маршрутных объявлений каждого маршрутизатора может содержать информацию, полученную от маршрутизаторов других локальных сетей или из выделенных линий. Роб, например, вероятно получил информацию от Мило и Робина об их сетях, и он может передавать туда пакеты данных. Они содержат информацию о собственных связях маршрутизатора и объявления о связях сети. Базы данных теперь синхронизированы с выделенным маршрутизатором, которым является Джон. Джон суммирует свою базу данных с каждой базой данных своих соседей — базами Фреда, Роба и Джеффа — индивидуально. В каждой cинхронизирующейся паре объявления, найденные только в какой-либо одной базе, копируются в другую. Выделенный маршрутизатор, Джон, распространяет новые объявления среди других маршрутизаторов своей локальной сети. Например, объявления Мило и Робина передаются Джону Робом, а Джон, в свою очередь, передает их Фреду и Джеффри. Обмен информацией между базами продолжается некоторое время, и пока он не завершится, маршрутизаторы не будут считать себя работоспособными. После этого они себя таковыми считают, потому что имеют всю доступную информацию о сети.

      Посмотрим теперь как Робин вычисляет маршрут через сеть. Две из связей, присоединенных к его портам, представляют линии T-1, а одна - линию 56 Кб/c. Робин сначала обнаруживает двух соседей — Роба с метрикой 65 и Мило с метрикой 1785. Из объявления о связях Роба Робин обнаружил наилучший путь к Мило со стоимостью 130, поэтому он отверг непосредственный путь к Мило, поскольку он связан с большей задержкой, так как проходит через линии с меньшей пропускной способностью. Робин также обнаруживает транзитную локальную сеть с выделенным маршрутизатором Джоном. Из объявлений о связях Джона Робин узнает о пути к Фреду и, наконец, узнает о пути к маршрутизаторам Келли и Джеффу и к их тупиковым сетям.

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