Еще будучи студентом-первокурсником, впервые в жизни столкнувшимся с компьютерными технологиями (это были мощные по тем временам 386-е машины), я долго ломал голову, каким образом компьютер всегда знает точное время. Потом, конечно, стало ясно, что время-то вводится вручную и хранится в недрах машины при поддержке маленькой батарейки...
Впоследствии возникли и другие вопросы: где гарантия, что это время точное и не "плывет" постепенно? Можно ли автоматизировать его коррекцию, не прибегая к способу "мануальной" синхронизации с наручными часами? Каков, в конце концов, собственно механизм этого процесса?
Попытаемся ответить на все эти вопросы. Забегая вперед, скажу, что, как оказалось, и в самом деле время ползет потихоньку "в сторону", и автоматическая коррекция его вполне возможна, и механизм однозначен и отлажен.
С развитием сети Интернет появилась возможность решить большинство проблем, связанных с поддержанием точного времени, посредством специальных протоколов, среди которых NTP (Network Time Protocol), DTSS (Digital Time Synchronization Protocol). Несмотря на легкость процесса для конечного пользователя (который, впрочем, может и вовсе не участвовать в коррекции времени), сам алгоритм решения достаточно интересен и не так прост, как может показаться на первый взгляд.
В основу используемой большинством стран стандартной временной шкалы - UTC (Coordinated Universal Time) положены величина промежутка времени суточного вращения Земли вокруг своей оси и григорианский календарь, учитывающий период вращения Земли вокруг Солнца. Временная шкала UTC, в свою очередь, корректируется на основе сведений атомных часов (International Atomic Time, TAI) путем "вставки" соответствующего количества секунд со знаком плюс или минус примерно раз в 18 месяцев. В данном случае речь идет именно о секундах, так как на больший временной интервал шкала не разбалансируется. [Прим. ред. CITForum.ru: наши читатели указали, что UTC определяется не совсем так. Более точное определение есть, например, здесь]
Шкала UTC, как основная, применяется в самых различных сферах: радио- и спутниковых навигационных системах, телефонных модемах, портативных часах и т. д. Специальные узкоцелевые ресиверы сигналов времени используются во множестве систем, для работы которых важна исключительная точность временной шкалы - это, например, системы глобального позиционирования GPS, а также другие устройства и службы, чья работа находится под пристальным внимание государства, ведь вопрос коррекции времени имеет, как правило, четкий юридический фундамент.
Исходя из соображений цены и удобства применения, нет никакого смысла использовать приемники сигналов точного времени с каждым конечным клиентским компьютером (да и вообще с любым устройством, отображающим текущее время). Тем не менее есть прямая необходимость задействовать некоторое количество компьютеров в качестве первичных серверов времени, установив на них оборудование, принимающее сигналы точного времени, и программное обеспечение, обслуживающее эту специфическую аппаратуру. Первичные серверы времени выступают в качестве носителей эталонного времени для намного большего числа серверов второго уровня, относительно которых в свою очередь корректируют время клиентские устройства.
Вот почему и возникла необходимость в специальном протоколе, способном считывать и интерпретировать сигналы времени с приемника, передавать считанное время клиентам и регулировать клиентские часы. Наиболее популярный из существующих ныне протоколов - Network Time Protocol (NTP). О нем и пойдет речь.
Основные положения протокола синхронизации
По большому счету основная задача протокола синхронизации времени - максимально точно определить разницу между показаниями часов сервера и часов клиента. Различные современные протоколы синхронизации используют разнообразные методы для определения этой разницы, но все они подчинены общей глобальной модели. По запросу сервер высылает сообщение, включающее текущие показания часов, или "отметку времени" (timestamp). Клиент записывает собственную отметку времени в момент прибытия сообщения сервера. Для достижения максимальной точности клиенту необходимо измерить задержку распространения ответа "сервер-клиент" и таким образом выяснить полную величину смещения показаний часов относительно часов сервера.
Поскольку невозможно определить величину задержки распространения в одну сторону, если известна актуальная величина смещения, протокол измеряет общую "транспортную" задержку ("клиент - сервер" плюс "сервер - клиент") и предполагает, что время распространения в одну и другую сторону одинаково. Это разумные рамки условностей, которых, к сожалению, не избежать - в сегодняшней сети Интернет маршруты прохождения данных и, соответственно, ассоциированные с ними временные задержки могут значительно варьироваться по понятным причинам.
Сообщество серверов и клиентов, обслуживаемых единым протоколом синхронизации времени, может быть очень большим. Например, "община" сети Интернет, в которой используется протокол NTP, в 2002 году насчитывала свыше 230 серверов времени первого уровня, получающих сигналы точного времени по радио, спутниковой связи или модему, а также примерно 100 тысяч серверов второго уровня и различных клиентов.
В дополнение к этому имеются многие тысячи "единовременных" локальных образований в крупных правительственных, корпоративных и университетских компьютерных сетях. Каждое образование представляет собой древовидную структуру или подсеть с серверами времени первого уровня, находящимися в корне всей структуры, и вторичными серверами и клиентами - по нарастающей. Каждый последующий уровень сервера (первичный - вторичный - третичный) во всей иерархии носит название "уровень стратума".
В больших сетях необходимо на каждом уровне стратума вводить избыточные серверы синхронизации и запасные сетевые маршруты, для того чтобы свести к минимуму риск программных и аппаратных сбоев, нарушения сетевых связей. Кстати, существуют довольно интересные данные о достоверности времени на серверах самого высокого уровня. Более 30% серверов уровня стратум-1 имеют погрешность более чем 10 секунд, а несколько их экземпляров - даже один год. По имеющимся сведениям, реально доверять можно лишь примерно 28% серверов данного уровня.
Протоколы синхронизации работают в одном или нескольких ассоциативных режимах, зависящих от дизайна этих протоколов. Как в NTP, так и в DTSS предусмотрены клиент-серверные режимы, называемые также master/slave. NTP также поддерживает симметричный режим синхронизации, позволяющий двум равным по уровню стратума серверам синхронизироваться друг с другом для взаимной коррекции показаний часов. И NTP, и DTSS допускают широковещательный режим работы - причем множество клиентов может синхронизироваться с одним или несколькими серверами. Это сделано для уменьшения сетевого трафика в сетях с большим количеством собственных клиентов. В случае NTP, например, широковещательная работа полезна, если подсеть принадлежит нескольким сетям.
Бывает, что в крупных компьютерных сетях управление конфигурированием синхронизации времени превращается в серьезную проблему. Для протоколов NTP и DTSS существуют различные схемы индексирования общедоступных сетевых баз и служб управления каталогами для более легкого обнаружения в сети оптимальных серверов синхронизации. Оба протокола используют широковещательные режимы работы, но, поскольку клиенты "в чистом виде" не могут откалибровать транспортную задержку, точность регулировки локального времени клиента может значительно упасть.
Применительно к протоколу NTP клиент определяет задержку для сервера, который является первым обнаруженным в режиме "клиент - сервер", затем клиент переходит в режим "только слушать". Вдобавок NTP-клиент может распространять специальное широковещательное сообщение, чтобы попросить близлежащие серверы отрегулировать клиентское время, затем, при получении ответа от одного или несколих серверов, клиент возвращается в привычный режим "клиент - сервер".
Аспекты безопасности
Надежный сервис сетевой синхронизации времени нуждается в определенных условиях для предотвращения случайных или злонамеренных атак на серверы и клиентские ПК внутри сети. Надежность требует от клиентов возможности определить подлинность полученных от серверов синхронизации сведений, а также удостовериться, что данные действительно получены от верного сервера и не были сгенерированы или подделаны злоумышленником.
Чем грозит подделка показаний времени на бытовом уровне? Представим себе, что намеренно "сбиты" часы на почтовом сервере крупной организации: вместо 2005 года значится, например, 2020-й. В итоге вся корреспонденция имеет огромные шансы никогда не дойти до адресата, поскольку либо клиентская почтовая программа, либо другие почтовые серверы сразу заподозрят неладное и удалят такие письма без предупреждений и сожалений. Необходимо обеспечить возможность проверки подлинности данных любым клиентом для любого сервера синхронизации с использованием только публичной информации. Это целиком относится к таким повсеместным сетевым сервисам, как службы каталогов, управление ключами шифрования и синхронизация времени.
Протокол NTP предусматривает возможность криптографической аутентификации индивидуальных серверов с помощью симметричного шифрования, при котором клиенты проверяют подлинность серверов синхронизации времени, используя разделяемые секретные ключи. Механизм распространения ключей не относится к собственно протоколу NTP, и это может быть достаточно неудобное и "хрупкое" мероприятие, если имеется большое число потенциальных клиентов. Современное шифрование на основе публичных ключей представляет собой средство для надежного связывания идентификационных атрибутов сервера и сопряженных с ними публичных значений с использованием доступных служб каталогов. Однако такой подход автоматически подразумевает высокие накладные расходы на вычисления, особенно в случае большого количества критичных к временным значениям клиентов, что типично для NTP-серверов. К тому же здесь существуют уникальные проблемы, которые заключаются во взаимодействии механизмов аутентификации и синхронизации, так как в данной ситуации один механизм не может успешно работать без другого.
Последняя, четвертая ревизия протокола NTP (NTPv4) обладает переработанной моделью безопасности и схемой подтверждения подлинности с поддержкой шифрования как на основе разделяемых, так и публичных ключей. При работе над вариантом с публичными ключами особое внимание было уделено максимальному снижению риска вторжения, уменьшению требуемой вычислительной мощности и исключению возможных точек взлома протокола.
Компьютерное моделирование времени и анализ ошибок
Большинство компьютеров содержат в составе аппаратной части кварцевый генератор с резонансной стабилизацией и аппаратный счетчик, генерирующий процессорные прерывания через интервалы, равные нескольким миллисекундам. При каждом прерывании к переменной, представляющей собой текущее локальное внутрикомпьютерное время, добавляется величина, на компьютерном сленге называемая "тик" (или "миг"). Переменная-время может быть прочитана операционной системой и приложениями, а также изменена (установлена) под влиянием внешнего программного или аппаратного воздействия. Однажды установленное, компьютерное время получает постоянное приращение с номинальным темпом, зависящим от величины тика. Ядра некоторых наиболее распространенных операционных систем имеют программные механизмы увеличения или уменьшения величины тика на небольшое фиксированное значение, для того чтобы произвести заданную корректировку компьютерного времени не скачкообразно, а плавно, в течение нескольких последующих тиков - время как бы искуственно замедляется или ускоряется.
Напомним, что часы операционной системы и аппаратные часы CMOS вовсе не одно и то же, протоколы коррекции времени работают в основном с операционной системой, а ОС либо самостоятельно, либо с помощью каких-то утилит вмешивается в работу часов CMOS. Неточность компьютерного времени проявляется вследствие множества факторов - это могут быть сетевые транспортные задержки, латентность аппаратного и программного обеспечения, а также банальная нестабильность кварцевого генератора. Время клиента относительно времени сервера может быть вычислено как следующая функция:
T(t) = T(t0) + R(t - t0) + ½D(t - t0)2
Здесь t
- текущее время; T
- смещение времени в момент последней коррекции t0
; R
- смещение тактовой частоты генератора; D
- дрейф вследствие "старения" резонатора. Все три слагаемых функции содержат как систематические смещения, подлежащие коррекции, так и случайные величины, которые принципиально не могут быть подправлены. Некоторые протоколы коррекции, например DTSS, работают лишь с первым из трех слагаемых, а, например, NTP - вычисляют первые два слагаемых. Ошибки, вызванные пренебрежением третьим слагаемым (безусловно, играющим роль при различных прецизионных применениях вычислительной техники), незначительны и в большинстве случаев перекрываются погрешностями первых двух слагаемых.
Протокол NTP оценивает T(t0)
(и R
, где необходимо) в постоянные промежутки времени и производит корректировку часов с целью уменьшения T(t)
в будущем. В общем случае R
может иметь систематические смещения, равные несколько сот герц на миллион в ту или иную сторону, вызванные в первую очередь изменениями температуры окружающей среды. Если периодически не производить коррекцию, суммарная суточная погрешность может достичь нескольких секунд в сутки. Для того чтобы результирующие ошибки не превышали номинальных значений, алгоритмы протокола NTP периодически вычисляют T
и R
- с целью компенсировать такие ошибки и через определенные интервалы скорректировать системное время. На практике это означает, что, например, для достижения номинальной точности в десять миллисекунд требуется синхронизация клиента с сервером с интервалом в десять минут.
Анализ кварцевых генераторов с резонансной стабилизацией показывает: ошибки являются функцией времени, а это автоматически подтверждает необходимость выдерживать интервал между "сверкой часов". Установлено, что, если интервал между синхронизациями превышает несколько сотен секунд, погрешность протокола доминирует над аппаратным "поползновением" времени, если же интервал менее нескольких сотен секунд, то в значительно большей степени проявляются программные "сдвиги".
Ошибки протокола накапливаются на всех уровнях стратума, начиная с наивысшего, затем распространяются по более низким уровням и в конце-концов достигают клиентов. Это выглядит угрожающе, но есть возможность предусмотреть подобные ошибки, например, статистическими методами, как в реализации протокола NTP.
Принципы корректировки
Существует масса сфер, где необходимо точное знание текущего времени, скажем, управление трафиком воздушных судов. Такие приложения должны обеспечиваться гарантиями, что локальное компьютерное время корректно и находится внутри определенных рамок относительно заданной временной шкалы - как правило, UTC. Столь строгие рамки предопределяют некоторые очевидные аксиомы. Так, наибольшая погрешность при чтении удаленного времени сервера не может превысить половину общей транспортной задержки.
Принципы корректировки системного времени требуют, чтобы его значение наращивалось монотонно, а потому двух успешных считываний значений времени одновременно быть просто не может, эти значения никогда не будут равны. Такое положение вещей очевидно в случае, если латентность при считывании значений превосходит аппаратную разрешающую способность. В современных микропроцессорах задержки считывания имеют значения на уровне микросекунд, а системное время в нынешних операционных системах отсчитывается на уровне наносекунд (оригинальное ядро ОС UNIX оперировало еще микросекундами).
По своей природе корректировка времени представляет собой непрерывный процесс, заключающийся в последовательности сверок показаний каждого из нескольких доступных серверов с результирующей установкой верного системного времени.
Протокол NTP предполагает использование серверов синхронизации, для которых транспортная задержка будет минимальной. Алгоритм коррекции накапливает образцы смещений/задержек в специальном окне образцов и выбирает сэмпл, ассоциированный с наименьшей задержкой. Теоретически лучшие результаты в плане точности достигаются с увеличением размеров окна, но из соображений стабильности работы размер окна составляет примерно 8 сэмплов.
Похожий принцип может быть использован при выборе подмножества серверов для синхронизации или объединением их временных смещений для коррекции времени. Тем не менее различные серверы часто отображают различные систематические смещения, в силу этого статистика всех серверов бывает недостаточно убедительной. И тогда могут оказаться полезными некоторые алгоритмы из мира кластеров. Один из них нашел применение в реализации протокола NTP. Смещения от различных серверов сортируются в соответствии с показателем качества, после чего вычисляются отклонения значений различных серверов относительно среднего значения смещения. Затем постепенно отбрасываются "неблагонадежные" серверы, а конечный результат - просто средняя величина от оставшихся серверов.
Послесловие
В заключение хотелось бы отметить наиболее значительные этапы развития протокола NTP. Первая реализация этой разработки, имевашая название Internet Clock Service, увидела свет в 1980 году, - на тот момент точность корректировки времени составляла сотни миллисекунд, а единственным применением для протокола коррекции времени был протокол маршрутизации HELLO. Ранние версии протокола синхронизации не учитывали компенсацию каких-либо частотных погрешностей.
Первая полноценная редакция NTP появилась в 1988 году. Данная версия уже поддерживала симметричные операции и режим "клиент-сервер". Версия 2, способная проводить аутентификацию на основе симметричных ключей (используя DES-CBC), вышла год спустя. Параллельно вышла аналогичная по своей сути разработка DTSS от корпорации DEC.
Разработчики NTP прониклись некоторыми передовыми идеями, нашедшими отражение в реализации DTSS, и вскоре, в 1992 году, опубликовали спецификации версии NTP 3. Третья редакция характеризуется пересмотренными алгоритмами коррекции и наличием широковещательного режима работы.
По информации разработчиков, создание NTPv4 началось в 1994 году. На сегодняшний день существует развитая система контроля за развитием этого проекта-ветерана, и любой пользователь, полагающий, что он может улучшить действующую реализацию, дополнить протокол возможностями или указать на имеющиеся ошибки, найдет самую горячую поддержку среди разработчиков.