FreeBSD: Сервер точного времени на базе ntpd
FreeBSD: Сервер точного времени на базе ntpd
В Сети имеется большое количество информации о синхронизации времени на компьютерах с Linux/Unix, однако, основная масса статей дает немного устаревшие рекомендации и очень кратко рассматривает вопросы выявления и устранения возможных проблем. В данной статье я постарался устранить вышеназванные недостатки.
Постановка задачи
В процессе создания любой корпоративной сети возникает вопрос организации синхронизации времени. Синхронизация времени базируется на протоколах NTP (Network Time Protocol) и SNTP (Simple Network Time Protocol). В большинстве случаев на одном из серверов корпоративной сети разворачивается главный сервер точного времени (далее — главный NTP-сервер), который синхронизируется с публичными серверами точного времени Интернета (далее — публичными NTP-серверами), и является источником точного времени для всех остальных компьютеров корпоративной сети. По умолчанию в состав операционной системы FreeBSD входит NTP-сервер ntpd(8). Данная статья посвящена его использованию в роли главного NTP-сервера корпоративной сети, организации синхронизации времени на компьютерах с FreeBSD (с учетом небольших расхождений в именах и форматах файлов конфигурации приведенная информация подойдет практически для любой операционной системы семейства Linux/Unix), а также устранению проблем, связанных с синхронизацией времени.
Исходные данные
Для решения рассматриваемой задачи не требуется установка какого-либо программного обеспечения, однако, во избежание недоразумений следует отметить, что все описанные действия выполнялись на серверах с FreeBSD 7.x RELEASE. Если Вы используете более раннюю версию операционной системы, может возникнуть необходимость обновления ее исходных текстов и пересборки мира.
Выбор публичных NTP-серверов
Для справки следует отметить, что одним из важнейших параметров NTP-сервера является stratum (в русской интерпретации — страта ) — величина, которая отражает уровень системных часов и может принимать значения: 0 — не специфицировано / недоступно, 1 — первичный ( primary ) эталон (например, атомные часы), 2-15 — вторичный ( secondary ) эталон, 16-255 — зарезервировано на будущее. Серверы, которые синхронизируются с серверами, имеющими stratum 1, получают stratum 2, серверы, которые синхронизируются с серверами, имеющими stratum 2, получают stratum 3 и т.д. В процессе выбора публичных NTP-серверов, с которыми будет синхронизироваться главный NTP-сервер, следует руководствоваться требованиями документа Rules of Engagement, которые не рекомендуют использовать публичные NTP-серверы, имеющие stratum 1, без веских оснований и призывают использовать не менее трех-пяти (из соображений надежности) публичных NTP-серверов, имеющих stratum 2. Список публичных NTP-серверов, имеющих stratum 2, содержится в документе Stratum Two Time Servers, из которого следует выбрать необходимое количество OpenAccess (публичных) NTP-серверов, расположенных в Вашей стране. Для проверки доступности и значения stratum выбранных серверов необходимо выполнить соответствующее число команд ntpdate -q <IP-адрес/FQDN NTP-сервера> . Эти команды служат для запроса времени и значений параметров stratum , offset , delay (последние два рассмотрены ниже) с удаленных NTP-серверов и не меняют состояние системных часов. Выводимые сообщения выглядят примерно так:
Если для всех NTP-серверов выводятся нулевые значения параметров и сообщения: «нет сервера, подходящего для синхронизации»:
Вам следует следует разрешить в брандмауэре входящий UDP-трафик со 123 порта серверов, расположенных в Интернет, и исходящий UDP-трафик на 123 порт серверов, расположенных в Интернет. Например, в случае ipfw(8) нужно добавить такие правила:
В момент написания статьи в Stratum Two Time Servers имелась информация о восьми публичных NTP-серверах, расположенных в России, при этом «мертвым» оказался только ntp.xland.ru , а остальные семь успешно используются в роли источников точного времени.
Настройка главного NTP-сервера
По умолчанию конфигурация ntpd хранится в файле /etc/ntp.conf . В моем случае этот файл имеет следующее содержимое:
В данном файле заданы следующие значения параметров: server . — список публичных NTP-серверов, с которыми синхронизируется наш сервер, restrict. — ограничения доступа к серверу (строка 8 — ограничение по умолчанию — доступ запрещен, строки 9-15 — ограничения доступа со стороны публичных NTP-серверов — запрещено изменять состояние сервера, запрашивать время и отправлять сообщения об исключениях, строки 16-18 — ограничения доступа со стороны клиентов — запрещено изменять состояние сервера и отправлять сообщения об исключениях), logfile — имя лог-файла. Описание всех опций, которые можно задать в файле конфигурации ntpd, содержится в ntp.conf(5). Для того, чтобы ntpd запускался при запуске операционной системы и делал начальную корректировку времени (это не опечатка, теперь ntpd умеет делать грубую начальную корректировку времени без помощи ntpdate) необходимо добавить в файл /etc/rc.conf строки:
По умолчанию лог ntpd имеет имя ntp.log и находится в папке /var/log . Для того, чтобы newsyslog(8) выполнял его ротацию, необходимо добавить в файл /etc/newsyslog.conf строку:
Данная строка обеспечивает усечение лога ntp при достижении размера 100 килобайт и сохранение трех предыдущих копий лога, сжатых архиватором bzip2(1) (Вы можете изменить эти параметры на свое усмотрение). На этом настройка внутреннего NTP-сервера завершается. Можно запустить сервер командой /etc/rc.d/ntpd start , а затем запросить его состояние командой /etc/rc.d/ntpd status . Если она выдаст сообщение ntpd is running as pid. , все нормально, если же — ntpd is not running , Вам следует найти и устранить ошибки в файлах конфигурации. После этого нужно подождать не менее получаса и выполнить команду ntpdate -q localhost . Если Вы внимательно следовали инструкциям, она выдаст сообщение о том, что NTP-сервер имеет stratum 3 и может использоваться для синхронизации времени:
Другим признаком корректной работы NTP-сервера можно считать появление в логе ntpd примерно таких сообщений:
Диагностика главного NTP-сервера
Для диагностики состояния главного NTP-сервера удобнее всего использовать утилиту ntpq(8), предназначенную для запроса различной информации у NTP-сервера. ntpq может работать как в интерактивном, так и в пакетном режиме, рассмотрение всех ее возможностей выходит далеко за рамки этой статьи. В контексте решаемой задачи более чем достаточно команды запроса состояния пиров — ntpq -p . (другие формы этой команды — ntpq -c peers , peers в интерактивном режиме). Информацию, выводимую командой ntpq -p , лучше пояснить на примере:
Строки данной таблицы соответствует публичным NTP-серверам, которые определены в файле /etc/ntp.conf , cтолбцы содержат следующие значения: маркер: ‘*’ — сервер, с которым в настоящий момент выполняется синхронизация, ‘#’ — сервер отобран для синхронизации, но дистанция до него превышает максимально возможную, ‘ο’ — сервер отобран для синхронизации и использует сигнал PPS, ‘+’ — сервер добавлен в список серверов, отобранных для синхронизации, ‘x’ — сервер использует некорректный алгоритм, ‘.’ — сервер выбран из конца списка серверов, отобранных для синхронизации, ‘-‘ — сервер отвергнут группирующим алгоритмом, пробел — сервер имеет слишком высокий stratum и/или не может быть проверен; remote — FQDN или IP-адрес сервера; refid — IP-адрес сервера с которым в настоящий момент выполняется синхронизация сервера из столбца remote ; st — stratum сервера; t — режим работы сервера: ‘u’ — unicast , ‘m’ — multicast , ‘b’ — broadcast , ‘-‘ — manycast ; when — время, прошедшее с момента последнего ответа сервера в секундах или ‘-‘ , если сервер еще ни разу не ответил (скорее всего, «умер», и сведения о нем пора удалить из файла конфигурации); poll — интервал опроса сервера в секундах (после запуска имеет небольшое значение, чтобы синхронизация происходила быстрее, с течением времени значение увеличивается); reach — состояние восьми последних попыток запроса времени у сервера в восьмеричном представлении (в случае успешной попытки устанавливается соответствующий бит); delay — задержка ответа сервера в секундах; offset — самое важное значение — различие локального времени и времени на сервере (с течением времени значение уменьшается, т.к. время становится более точным); jitter — дисперсия, дрожание фазы (более низкие значения обеспечивают более точную синхронизацию).
Синхронизация времени на остальных компьютерах с FreeBSD
Во избежание путаницы отмечу, что под «остальными компьютерами» в данном случае понимаются все компьютеры корпоративной сети с FreeBSD за исключением главного NTP-сервера. Средства FreeBSD позволяют реализовать два варианта синхронизации времени. Первый рассмотрен выше, и после замены публичных NTP-серверов на главный NTP-сервер подойдет для любого компьютера корпоративной сети с FreeBSD. Изменения касаются единственного файла конфигурации /etc/ntp.conf , который необходимо привести к следующему виду:
Второй вариант заключается в выполнении команды ntpdate -b <IP-адрес/FQDN внутреннего NTP-сервера> при запуске операционной системы и последующем выполнении команды ntpdate -s <IP-адрес/FQDN внутреннего NTP-сервера> каждый час. Ключ -b заставляет ntpdate принудительно использовать системный вызов settimeofday(2), предназначенный для грубой корректировки системного времени (по умолчанию, если локальное время время отличается от времени, полученного с NTP-сервера, менее чем на 0,5 секунд, ntpdate использует системный вызов adjtime(2), предназначенный для плавной корректировки системного времени), ключ -s включает перенаправление вывода в syslog(3). Таким образом эмулируется поведение NTP-сервера. Грубая корректировка времени при запуске операционной системы является очень важной операцией. Она позволяет избежать значительный скачок системного времени (и возможные проблемы в работе систем биллинга, статистики, СУБД и т.п.), который может произойти в том случае, если первая операция синхронизации времени будет выполнена позже, чем запустится операционная система, и локальное время будет отличаться от времени на NTP-сервере более чем на 0,5 секунд. Для того, чтобы команда грубой корректировки времени автоматически выполнялась при запуске операционной системы, следует добавить в файл /etc/rc.conf строки:
Для того, чтобы команда точной корректировки времени каждый час выполнялась с помощью cron(8), необходимо войти в систему под root’том , выполнить команду crontab -e , позволяющую внести изменения в crontab текущего пользователя (т.е. root’a ), и добавить строку:
На этом настройка второго варианта завершается. Я рассказал о нем лишь потому, что он существует и может использоваться, однако, у меня ни разу не возникало оснований для отказа от первого варианта.
Заключение
Я надеюсь, что не забыл ничего важного, и приведенной информации будет достаточно для корректной настройки и последующей отладки NTP-серверов на компьютерах Вашей корпоративной сети с FreeBSD и другими операционными системами семейства Linux/Unix.
Синхронизация времени с NTP сервером через GSM модем
Суть получения времени с NTP сервера сводится к посылки на него пустого(любого) UDP пакета. В ответ удаленный сервер вернет количество секунд, начиная с 1 января 1900года. Реализация отправки пакета на GSM модуле SIM сводится к нескольким этапам. Вначале необходимо зарегистрироваться в GPRS сети АТ командой, далее открыть соединение с удаленным сервером, затем послать сообщение, принять данные о времени и закрыть соединение. Полученные данные(четыре байта) необходимо преобразовать в формат хотя бы ЧЧ/ММ/СС, хотелось бы и дни и месяцы с годами определять, но мне достаточно знать часы, минуты и секунды. Время полученное с сервера пишем прямо в часы реального времени, которые есть в том же GSM модуле.
АТ команды работы GPRS в порядке их работы:
1)AT+CGATT=1 — команда регистрации в сети GPRS. Вернет ОК в случае успешной регистрации.
Реализующий её макрос:
Константы необходимые макросу:
Аналогично вычисляются остальные настройки.
3) Далее необходимо указать в каком виде будет вводится имя сервера:
AT+CDNSORIP=1-доменное имя сервера.
AT+CDNSORIP=0- имя сервера в виде IP адреса.
Будем использовать AT+CDNSORIP=1 так как IP адреса могут меняться.
Константа для макроса:
4) Открываем соединение.
AT+CIPSTART=”mode”,”domain name”,”port”
Здесь mode тип нашего протокола TCP либо UDP. NTP сервер поддержует UDP протокол.
domain name – адрес НТП сервера. Вот список известных мне НТП серверов:
ntp1.vniiftri.ru
ntp1.vniiftri.ru
port – порт по которому хотим послать запрос. Здесь я наткнулся на проблему. В описания везде указуют порт 123, но по нему ответ не приходит. Отвечает порт 37. Поэтому не удивляйтесь, что у меня не стандартный порт 123 а порт 37(!). Если Ты сможешь разобраться в этой заморочке, расскажи, я писал в несколько фирм, но некто мне не дал четкого ответа. Вообще NTP протокол разный, есть старые версии и есть более новые, вот по 37 порту идет старая версия протокола, вроде бы по 123 порту другой формат протокола, но при попытке послать пустой UDP пакет на 123 порт, в ответ нечего не приходит((. Поэтому я пользуюсь 37.
Команду открытия соединения реализуют два макроса:
Длина строки с НТП именем сервера также хранится в EEPROM и вычисляется аналогично настройкам GPRS.
Следует сказать, что у Нас два НТП сервера и в случае не удачи с первым можно попробовать со вторым.
После всех настроек можно попробовать коннект.
5) Прежде всего регистрируемся в сети GPRS командой AT+CGATT.
В последних трех строках Мы пробуем открыть соединение с NTP сервером по протоколу UDP на 37 порт.
6)Теперь если соединение удастся Нам вернется «0», это ОК (так как мы отключили текстовый информационный ответ от модуля командой ATV=0).
Проверяем ответ от модуля.
Далее если сервер готов к обмену данными он возвращает «8», это CONNECT OK
Если соединение не получится вернется:
4 – ERROR обычно этот ответ говорит о неверном адресе, порте и протоколе.
3 или 9 возвращается, если сервер занят.
Проверяем ответ от сервера.
Если все нормально попробуем послать UDP пакет.
7) Для передачи сообщений удаленному серверу существует команда
Реализуем её макросом
После ввода команды нужно дождаться приглашения для ввода сообщения.
Это знак > .
Чтобы получит овеет от NTP сервера необходимо отправить пустой UDP пакет.
usart0_write(0x1A); //Отправляем пустое сообщение.
В ответ от удаленного сервера могут вернуться следующие сообщения:
SEND OK -сообщение отправлено(но может не доставлено UDP же);
ERROR – соединение не установлено или отключено;
SEND FAIL – передача сообщения не прошла.
Причем эти сообщения будут в текстовом виде, в независимости от формата ответа модема (ATV=1 или ATV=0).
Проверяем ответ от сервера.
Проверка ответа реализована проверкой символа не встречающихся в этих сообщениях
SEND OK
SEND FAIL
ERROR
После получение подтверждения об отправке сообщения необходимо дождаться ответа от NTP сервера. Ответ прейдет четырьмя байтами, это количество секунд, начиная от 1 января 1900 года. Может случится что ответ будет приходит в течении секунды, может в течении часа, а может и вообще не прейти, так как используется UDP протокол, который не гарантирует доставку сообщения.
Поэтому в ожидании ответа используем таймаут, по истечению которого выходим из ожидания ответа и закрываем соединение.
8) Получаем время от сервера.
Теперь как ответ получен в виде четырех байт, его необходимо расшифровать. Я не заморачивался с вычислением года, месяца и дня. Достаточно занести эти настройки в RTC и периодически обновлять час, минуту и секунду RTC.
9) Для преобразования времени к формату ЧЧ/ММ/СС нужно целочисленно разделить полученный код на 86400. Это количество секунд в сутках, далее целочислено умножить этот ответ на 86400 и вычисть из полученного кода полученный ответ. В результате проделанной операции мы получим остаток секунд от полуночи, а далее вычисляем минуты и часы.
В переменных isec, ihours и imin находится время прямом формате.
Для того чтобы занести время в RTC модуля необходимо преобразовать его в BCD формат. Для чего я написал функцию делающее это преобразование BCDFormat(uint8_t hex) и обратное преобразование HEXFormat(uint8_t bcd). Я также прилагаю файл BCD.h.
В конце программы встречается макрос закрывающий соединение.
CIPSHUT
Вот его описание
Макрос завершает соединение и после его выполнения придет ответ
”0” — SHUT OK — соединение закрыто успешно
или
“4” – ERROR – соединение и не открывалось.
Делюсь опытом ESP8266 синхронизация времени с NTP сервером. UnixTime и конвертация времени.
Нашел и отладил утилиты синхронизации времени с NTP сервером, конвертации времени из UNIX формата (число секунд с 01.01.1970) в обычный и обратно. Что очень полезно для программирования событий на ESP 8266. Естественно, чтобы использовать их, необходимо, чтобы ESP8266 была подключена к сети с выходом в интернет. До того, как произойдет синхронизация (может не произойти с первого раза), она пытается это делать каждые 10 секунд, после этого — раз в сутки, т.к. есть встроенные часы по таймеру Tcker.h
Также прикладываю утилиты конвертации IP адреса в/из строкового формата.
gerkimuyda
New member
- #2
enjoynering
Active member
- #3
стандартные arduino примеры об этом не знают.
Вы бы взяли и рассказали как надо в картинках.
New member
- #4
стандартные arduino примеры об этом не знают.
Вы бы взяли и рассказали как надо в картинках.
CodeNameHawk
Moderator
- #5
enjoynering
Active member
- #6
CodeNameHawk
Moderator
- #7
Активный участник сообщества
- #8
enjoynering
Active member
- #9
Активный участник сообщества
- #10
Запрос у удаленного NTP всё равно не точен (тем более по примеру в данной теме ), без специальных алго фильтров и сотней опросов, и при единичном запросе его колбасит обычно на +-2 сек.
Зачем вообще зависучей игрушке время?
Напишите в поиске форума "синхронизация" — только по этому слову выпадут десятки тем и скетчей как получить и обработать время по NTP. Каждый, вновь заходящий, без поиска пишет новую тему и новый глюко-скетч, когда в SDK всё строено и вызывается парой команд, да в протоколе WiFi уже есть синхронизация, точность которой и не снилась NTP.
shuraf
Member
- #11
Chatlanin
New member
- #12
Активный участник сообщества
- #13
А на чем построены графики расхождения кварцев за отсчеты в 0.1 сек от температуры роутера и ESP в мкс ?
Всё в web-свалке, вам надо какую-то опцию включить при сборке проекта (забыл уже, т.к. у меня проектов много, а это было давно) и описать страничку HTML приема отсчетов c отображением в график на javascript и закинуть на диск web ESP. Тогда в любом броузере будет создавать аналогичный график Т.е. в данном случае такой синхронизации хватает для вывода звука на разнесенные колонки и триангуляции на источник звука в пару метров (с учетом скорости ветра)
Для отображения часов обычно ставят GPS и используют стандартный её выход строба секундных отсчетов. Но на Arduino невозможно даже с программным ФАПЧ получить точность внешних событий (изменений на GPIO, хоть по прерыванию) лучше 50 us из-за биений с запретами прерываний в системе.
Если поставите внешний MCU, то с бытовых GPS модулей и программным ФАПЧ сможете синхронизовать только вставку кадров (переключение на рекламу без срыва синхро) в транслируемое аналоговое телевидение и то с биениями.
Синхронизация времени по сети порт
Network Time Protocol
Network Time Protocol (NTP) — сетевой протокол для синхронизации внутренних часов компьютера с использованием сетей с переменной латентностью.
NTP использует для своей работы протокол UDP. Система NTP чрезвычайно устойчива к изменениям латентности среды передачи.
NTP использует алгоритм Марзулло (предложен Кейтом Марзулло (Keith Marzullo) из Университета Калифорнии, Сан-Диего), включая такую особенность, как учёт времени передачи. В версии 4 способен достигать точности 10 мс (1/100 с) при работе через Интернет, и до 0,2 мс (1/5000 с) и лучше внутри локальных сетей.
NTP — один из старейших используемых протоколов. NTP разработан Дэвидом Л. Миллсом (David L. Mills) из университета Дэлавера в 1985 году и в настоящее время продолжает совершенствоваться. Текущая версия — NTP 4.
NTP использует иерархическую систему «часовых уровней» (stratum). Уровень 1 синхронизирован с высокоточными часами, например, с системой GPS, ГЛОНАСС (Единая Государственная шкала времени РФ) или атомным эталоном времени. Уровень 2 синхронизируется с одной из машин уровня 1, и так далее.
Время представляется в системе NTP 64-битным числом (8 байт), состоящим из 32-битного счётчика секунд и 32-битного счётчика долей секунды, позволяя передавать время в диапазоне 2 32 секунд, с теоретической точностью 2 −32 секунды. Поскольку шкала времени в NTP повторяется каждые 2 32 секунды (136 лет), получатель должен хотя бы примерно знать текущее время (с точностью 50 лет). Также следует учитывать, что время отсчитывается с полуночи 1 января 1900 года, а не с 1970, поэтому из времени NTP нужно вычитать почти 70 лет (с учётом високосных лет), чтобы корректно совместить время с Windows или Unix-системами.
Наиболее широкое применение протокол NTP находит для реализации серверов точного времени. Для достижения максимальной точности предпочтительна постоянная работа программного обеспечения NTP в режиме системной службы. В семействе операционных систем Microsoft Windows, — это служба W32Time (модуль w32time.dll, выполняющийся в svchost.exe), Linux — сервис Ntpd.
Более простая реализация этого алгоритма известна как SNTP — простой синхронизирующий сетевой протокол. Используется во встраиваемых системах и устройствах, не требующих высокой точности, а также в пользовательских программах точного времени.
Подробная реализация протокола и системы в целом описана в:
NTP не следует путать с daytime protocol RFC 867 или time protocol RFC 868 (win программа FG Time Sync).
Часовые слои
NTP использует иерархическую, многоуровневую систему источников времени. Каждый уровень этой иерархии называется слоем, каждому слою присваивается номер, начиная с 0 (ноль) в верхней части. Уровень слоя определяет расстояние от эталонных часов и существует, чтобы предотвратить циклические зависимости в иерархии. Важно отметить, что слой не является показателем качества и надежности, это значит, что источник слоя 3 может дать сигнал более высокого качества, чем некоторые источники слоя 2. В основном, слои служат для распределения нагрузки и обеспечения большей площади покрытия. Это определение слоя также отличается от понятия часовых слоёв, используемых в телекоммуникационных системах.
Слой 0 — это высокоточные приборы служащие эталоном времени, такие как атомные (молекулярные, квантовые) часы, радиочасы или их аналоги. Обычно эти устройства не подключены к сети; вместо этого они подключены к локальному компьютеру (например, через интерфейс RS-232) и передают сигналы PPS для синхронизации.
Это компьютер, к которому напрямую подключены эталонные часы. Он выступает в качестве сетевого сервера времени и отвечает на NTP-запросы посылаемые компьютерами слоя 2.
Это компьютеры, которые получают время от серверов первого слоя, используя для этого протокол NTP. Обычно, компьютеры второго слоя обращаются к нескольким серверам первого слоя, и используя NTP-алгоритм, получают наилучший образец данных, отсеивая сервера с очевидно неверным временем. Компьютеры могут сравнивать свои данные с другими компьютерами своего слоя для получения стабильных и непротиворечивых данных на всех компьютерах слоя. Компьютеры второго слоя в свою очередь выступают в качестве серверов для компьютеров третьего слоя и отвечают на NTP-запросы.
Компьютеры третьего слоя работают точно так же как и компьютеры второго слоя, с той лишь разницей, что серверами для них являются компьютеры вышележащего второго слоя. Они так же могут выступать в качестве серверов для нижележащего слоя. NTP (в зависимости от версии) поддерживает до 256 слоев.