Як зробити так, щоб час per se не брехав, якщо у вас є мільйон великих і малих пристроїв, що взаємодіють через TCP/IP? Адже на кожному з них є годинник, а час має бути вірним на всіх. Цю проблему без ntp неможливо оминути.
Уявімо на одну хвилину, що в одному сегменті промислової ІТ інфраструктури виникли труднощі із синхронізацією сервісів за часом. Негайно починає збоїти кластерний стек Enterprise, розпадаються домени, майстри і Standby вузли безуспішно прагнуть відновити status quo.
Можлива також ситуація, коли зловмисник навмисно намагається збити час через MiTM або DDOS атаку. У такій ситуації може статися що завгодно:
- закінчиться термін дії паролів облікових записів користувачів;
- закінчиться термін дії X.509 сертифікатів;
- двофакторна автентифікація TOTP перестане працювати;
- бекапи «застаріють» і система видаляє їх;
- зламається DNSSec.
Зрозуміло, що кожен перший департамент ІТ зацікавлений у надійній роботі служб синхронізації часу, і добре б вони були надійні та безпечні у промисловій експлуатації.
Зламати NTP за 25 хвилин
Мережеві протоколи – мілініали мають одну особливість, вони давно і нікуди вже не годяться, але замінити їх не так легко навіть тоді, коли набирається критична маса ентузіастів та фінансування.
Основна претензія до класичного NTP у відсутності надійних механізмів захисту від зловмисників. Робилися різноманітні спроби вирішити цю проблему. Для цього спочатку впровадили механізм заздалегідь встановлених ключів для обміну симетричними ключами.
На жаль, цей спосіб себе не виправдав у сиді простої причини — він погано масштабується. Потрібне ручне налаштування на стороні клієнта в залежності від сервера. Це означає, що ось так просто не можна додати ще одного клієнта. Якщо на сервері NTP щось змінюється, потрібно перенастроювати всі клієнти.
Тоді придумали AutoKey, але відразу ж у ньому виявили низку серйозних уразливостей у самому дизайні алгоритму і від нього довелося відмовитись. Вся справа в тому, що початкове число (seed) містить лише 32-біта, воно занадто мало і не містить достатньо обчислювальної складності для лобової атаки.
- Key ID – симетричний 32-бітний ключ;
- MAC (message authentication code) - контрольна сума пакета NTP;
Autokey розраховується так.
Autokey=H(Sender-IP||Receiver-IP||KeyID||Cookie)Де H() – криптографічна хеш функція.
Для розрахунку контрольної суми пакети використовується та сама функція.
MAC=H(Autokey||NTP packet)Так виходить, що вся цілісність перевірок пакетів тримається на автентичності кукіс. Оволодівши ними, можна відновити autokey і потім підробити MAC. Проте сервер NTP за її генерації використовує початкове число (seed). Саме тут криється каверза.
Cookie=MSB_32(H(Client IP||Server IP||0||Server Seed))Функція MSB_32 відрізає від результату обчислення md5 хеша 32 старших біта. Клієнтський cookie не змінюється, поки параметри сервера незмінні. Далі зловмиснику залишається лише відновити початкове число та отримати можливість самостійно генерувати куки.
Для початку слід підключитися до сервера NTP як клієнта і отримати куки. Після цього методом перебору зловмисник відновлює початкове число, дотримуючись простого алгоритму.
Алгоритм атаки на обчислення початкового числа шляхом перебору.
for i=0:2^32 − 1 do
Ci=H(Server-IP||Client-IP||0||i)
if Ci=Cookie then
return i
end if
end forIP адреси відомі, так що залишається лише створити 2^32 хеша до тих пір, поки створений cookie не збігається з тим, що отриманий від NTP сервера. На звичайній домашній станції з Intel Core i5 на це піде 25 хв.
NTS - новий Autokey
Миритися з такими дірками у безпеці Autokey було неможливо і у 2012 р. з'явилася протоколу. Для скомпрометованої назви вирішили провести ребрендинг, так Autokey v.2 охрестили Network Time Security.
Протокол NTS є розширенням безпеки NTP і нині підтримує лише одноадресний режим (unicast). Він дає надійний криптографічний захист від маніпуляцій пакетами, запобігає відстеженню, добре масштабується, стійкий до втрати мережевих пакетів і призводить до найменших втрат точності, що виникають у процесі захисту з'єднання.
З'єднання NTS складається з двох етапів, в яких використовуються протоколи нижнього рівня. на першому На етапі клієнт і сервер домовляються про різні параметри з'єднання і обмінюються куки, що містять ключі з усім супутнім набором даних. на другому На етапі відбувається власне захищений NTS сеанс між клієнтом і сервером NTP.

NTS складається з двох протоколів нижнього рівня: Network Time Security Key Exchange (NTS-KE), ініціалізація безпечного з'єднання поверх TLS і NTPv4 - останньої інкарнації протоколу NTP. Трохи докладніше звідси нижче.
Перший етап - NTS KE
На даному етапі NTP клієнт ініціює TLS 1.2/1.3 сеанс окремого TCP з'єднання з сервером NTS KE. Під час цієї сесії відбувається таке.
- Сторони визначають параметри алгоритм для другого етапу.
- Сторони визначають другий протокол нижнього рівня, але на даний момент лише NTPv4 підтримується.
- Сторони визначають IP адресу та порт NTP сервера.
- NTS KE сервер видає куки під NTPv4.
- Сторони витягують із матеріалу куки пару симетричних ключів (C2S та S2C).
Такий підхід має велику перевагу в тому, що все навантаження щодо передачі секретної інформації параметрів з'єднання лягає на перевірений та надійний протокол TLS. Тим самим відпадає необхідність винаходити власний велосипед для безпечного рукостискання NTP.
Другий етап - NTP під захистом NTS
На другому етапі клієнт безпечно синхронізує час із сервером NTP. З цією метою він передає чотири спеціальні розширення (extension field) у структурі NTPv4 пакета.
- Unique Identifier Extension містить випадковий nonce для запобігання атакам шляхом повтору.
- NTS Cookie Extension містить один з наявних у клієнта NTP cookie. Оскільки тільки клієнт має симетричні AAED ключі C2S і S2C, сервер NTP повинен витягти їх з матеріалу куки.
- NTS Cookie Placeholder Extension спосіб для клієнта запросити додаткові куки з сервера. Це розширення необхідно, щоб відповідь сервера NTP не була набагато довшою, ніж запит. Це дозволяє запобігти атакам посилення.
- NTS Authenticator and Encrypted Extension Fields Extension містить шифр алгоритму AAED з C2S ключем, заголовком NTP, часовими відмітками, і згаданими вище EF як супутні дані. Без цього розширення можна підробити часові позначки.

Отримавши запит від клієнта, сервер перевіряє справжність пакета NTP. Для цього він повинен розшифрувати куки, вилучити алгоритм AAED та ключі. Після успішної перевірки пакета NTP на валідність сервер відповідає клієнту в наступному форматі.
- Unique Identifier Extension – дзеркальна копія клієнтського запиту, міра проти атак шляхом повтору.
- NTS Cookie Extension більше куки для продовження сеансу.
- NTS Authenticator and Encrypted Extension Fields Extension містить шифр AEAD із S2C ключем.
Другий потиск рук можна повторити багато разів, минаючи перший етап, так як кожен запит і відповідь дає клієнту додаткові куки. Це дає ту перевагу, що щодо ресурсомісткі TLS операції обчислення та передачі PKI даних поділяються на кількість повторних запитів. Це особливо зручно для спеціалізованих FPGA хронометрів, коли весь основний функціонал можна запакувати в кілька функцій з області симетричної криптографії, передавши весь стек TLS на інший пристрій.
NTPSec
У чому особливість NTP? Незважаючи на те, що автор проекту Dave Mills намагався якнайкраще документувати свій код, рідкісний програміст зуміє розібратися в хитросплетіннях алгоритмів синхронізації часу 35-річної давності. Частина коду написана до епохи POSIX, а Unix API тоді дуже відрізнявся від того, що використовується в наші дні. Крім того, потрібні знання зі статистики, щоб очистити сигнал від перешкод на шумних лініях.
NTS була не першою спробою відремонтувати NTP. Після того, як зловмисники навчилися використовувати вразливості NTP для посилення DDoS атак, зрозуміли, що потрібні радикальні зміни. І поки готувалися і доводилися до пуття чернетки NTS, National Science Foundation США наприкінці 2014 р. терміново виділив грант на модернізацію NTP.
Робочу групу очолив не аби хто, а — один із засновників та стовпів спільноти Open Source та автор книги . Насамперед Ерік з товаришами спробували перенести код NTP з платформи BitKeeper на git, але не було. Лідер проекту Harlan Stenn був проти цього рішення і переговори зайшли у глухий кут. Тоді було вирішено форкнути код проекту, тому виник NTPSec.
Солідний досвід, у тому числі робота над GPSD, математичний бекграунд та магічна навичка читання стародавнього коду – Ерік Реймонд був саме тим хакером, який міг витягти такий проект. У команді знайшовся фахівець з міграції коду і лише за 10 тижнів NTP на GitLab-е. Робота закипіла.
Команда Еріка Раймонда взялася за справу так само, як Огюст Роден під час роботи з брилом каменю. Видавши 175 KLOC старого коду, їм вдалося значно скоротити площу атаки, закривши безліч дірок безпеки.
Ось неповний список тих, хто потрапив під роздачу:
- Недокументовані, застарілі, застарілі або зламані refclock.
- бібліотека ICS, що не використовується.
- libopts/autogen.
- Старий код для Windows.
- ntpdc.
- Autokey.
- C-код ntpq переписаний на Python.
- C-код sntp/ntpdig переписаний на Python.
Крім очищення коду, були і у проекту були й інші завдання. Ось неповний перелік досягнень:
- Значно посилено захист коду від переповнення буфера. Щоб запобігти переповненню буфера, всі небезпечні рядкові функції (strcpy/strcat/strtok/sprintf/vsprintf/gets) замінили безпечними версіями, які реалізують обмеження розміру буфера.
- Додано підтримку NTS.
- Десятиразово підвищили точність тимчасового кроку за допомогою прив'язки до фізичного обладнання. Це пов'язано з тим, що сучасний комп'ютерний годинник став набагато точнішим за той, що був у момент зародження NTP. Найбільше від цього виграли GPSDO та виділені радіостанції часу.
- Кількість мов програмування скоротилася до двох. Замість скриптів Perl, awk і навіть S тепер суцільний Python. За рахунок цього більше можливостей повторного використання коду.
- Замість локшини скриптів autotools проект став використовувати систему збирання програмного забезпечення .
- Оновили та реорганізували документацію проекту. З суперечливої та місцями архаїчної колекції документів створили цілком стерпну документацію. Кожен ключ командного рядка і кожна сутність конфігурації мають єдину версію правди. Крім того, сторінки посібника та веб-документація тепер створюються з тих самих основних файлів.
NTPSec доступний ряд Linux дистрибутивів. В даний момент остання стабільна версія 1.1.8 для Gentoo Linux - передостання.
(1:696)$ sudo emerge -av ntpsec
These are the packages that would be merged, in order:
Calculating dependencies... done!
[ebuild R ] net-misc/ntpsec-1.1.7-r1::gentoo USE="samba seccomp -debug -doc -early -gdb -heat -libbsd -nist -ntpviz -rclock_arbiter -rclock_generic -rclock_gpsd -rclock_hpgps -rclock_jjy -rclock_local -rclock_modem -rclock_neoclock -rclock_nmea -rclock_oncore -rclock_pps -rclock_shm -rclock_spectracom -rclock_trimble -rclock_truetime -rclock_zyfer -smear -tests" PYTHON_TARGETS="python3_6" 0 KiB
Total: 1 package (1 reinstall), Size of downloads: 0 KiB
Would you like to merge these packages? [Yes/No]
Хронія
Була ще одна спроба замінити старий NTP безпечніший аналог. Chrony, на відміну від NTPSec, написаний з нуля і призначений для надійної роботи в широкому діапазоні умов, включаючи нестабільні мережеві з'єднання, часткова доступність або перевантаження мережі та зміни температури. Крім того chrony має й інші переваги:
- chrony може швидше синхронізувати системний годинник з більшою точністю;
- chrony менше, споживає менше пам'яті та звертається до процесора тільки тоді, коли це необхідно. Для економії ресурсів та енергії це великий плюс;
- chrony підтримує мітки часу на апаратному рівні Linux, що забезпечує надзвичайно точну синхронізацію в локальних мережах.
Втім, у chrony відсутні деякі можливості старого NTP такі, як широкомовний та багатоадресний (multicast) клієнт/сервер. Додатково класичний NTP підтримує більше ОС і платформ.
Для відключення функціональності сервера та NTP запитів до процесу chronyd достатньо прописати port 0 у файл chrony.conf. Це робиться в тих випадках, коли немає потреби обслуговувати час для клієнтів NTP або однорангових вузлів. Починаючи з версії 2.0, порт сервера NTP відкритий тільки в тих випадках, коли доступ дозволений директивою allow або відповідною командою, або ж налаштований одноранговий вузол NTP, або використовується директива Broadcast.
Програма складається із двох модулів.
- chronyd – сервіс, що працює у фоновому режимі. Він отримує інформацію про різницю системного годинника із зовнішнім сервером часу і коригує локальний час. Він також реалізує протокол NTP і може бути клієнтом або сервером.
- chronyc - утиліта командного рядка для моніторингу та контролю програми. Використовується для тонкого налаштування різних параметрів сервісу, наприклад, дозволяє додавати або видаляти сервери NTP у той час, як chronyd продовжує працювати.
Починаючи з 7-ї версії RedHat Linux chrony як служба синхронізації часу. Пакет також доступний для інших Linux-дистрибутивів. Остання стабільна версія 3.5 готується до виходу v4.0.
(1:712)$ sudo emerge -av chrony
These are the packages that would be merged, in order:
Calculating dependencies... done!
[binary N ] net-misc/chrony-3.5-r2::gentoo USE="adns caps cmdmon ipv6 ntp phc readline refclock rtc seccomp (-html) -libedit -pps (-selinux)" 246 KiB
Total: 1 package (1 new, 1 binary), Size of downloads: 246 KiB
Would you like to merge these packages? [Yes/No]
Як настроїти власний віддалений сервер chrony в інтернеті для синхронізації часу в офісній мережі Далі приклад налаштування на VPS.
Приклад налаштування Chrony на RHEL/CentOS на VPS
Давайте тепер трохи потренуємось та піднімемо свій власний NTP сервер на VPS. Це дуже просто, достатньо вибрати потрібний тариф на сайті RuVDS, отримати готовий сервер і набрати з десяток нескладних команд. Для наших цілей цілком підійде такий варіант.

Переходимо до налаштування сервісу і насамперед ставимо пакет chrony.
[root@server ~]$ yum install chronyRHEL 8/CentOS 8 використовують інший пакетний менеджер.
[root@server ~]$ dnf install chronyПісля встановлення chrony потрібно запустити та активувати сервіс.
[root@server ~]$ systemctl enable chrony --nowЗа бажанням можна внести редагування в /etc/chrony.conf, замінивши сервера NPT на найближчі локальні для скорочення часу відгуку.
# Use public servers from the pool.ntp.org project.
# Please consider joining the pool (http://www.pool.ntp.org/join.html).
server 0.ru.pool.ntp.org iburst
server 1.ru.pool.ntp.org iburst
server 2.ru.pool.ntp.org iburst
server 3.ru.pool.ntp.org iburst
Далі налаштовуємо синхронізацію NTP сервера із вузлами із зазначеного пулу.
[root@server ~]$ timedatectl set-ntp true
[root@server ~]$ systemctl restart chronyd.service
Необхідно також відкрити назовні NTP порт, інакше міжмережевий екран блокуватиме вхідні з'єднання від клієнтських вузлів.
[root@server ~]$ firewall-cmd --add-service=ntp --permanent
[root@server ~]$ firewall-cmd --reload
На стороні клієнта достатньо правильно виставити часовий пояс.
[root@client ~]$ timedatectl set-timezone Europe/MoscowУ файлі /etc/chrony.conf вказує IP або назву хоста нашого VPS сервера, на якому запущено NTP server chrony.
server my.vps.serverІ, нарешті, запуск синхронізації часу на клієнта.
[root@client ~]$ systemctl enable --now chronyd
[root@client ~]$ timedatectl set-ntp true
Наступного разу розповім, які варіанти синхронізації часу без інтернету.
Джерело: habr.com
