Корпоративная NTP-инфраструктура для банка с точностью до микросекунд

Исходная ситуация: хаос во времени

В январе 2026 года банк ФинансБанк прошёл аудит PCI DSS, в ходе которого аудиторы зафиксировали критическое замечание: расхождение часов между серверами достигало 15 секунд. Для банка с 2 000+ транзакций в секунду это катастрофа.

Проблемы, вскрытые аудитом:

  • PCI DSS 10.4 требует синхронизации часов всех систем с точностью ±1 секунда — банк не соответствовал
  • Kerberos-аутентификация в Active Directory отказывала при drift >5 минут — сотрудники теряли доступ к системам
  • Логи из разных систем невозможно было коррелировать — при расследовании инцидента безопасности в ноябре 2025 это стоило команде SOC трёх дней ручной сверки
  • Ордера на бирже привязаны к timestamp — расхождение в 2 секунды приводило к неверному порядку исполнения

Корневая причина: 340 серверов синхронизировались с публичным NTP Pool (pool.ntp.org), который в российской зоне к осени 2024 года практически рухнул — из 140 серверов осталось 4. Оставшиеся серверы были перегружены и отдавали время с джиттером до 500 мс.

Архитектура решения: Stratum-иерархия

Мы спроектировали трёхуровневую NTP-иерархию с полным резервированием на каждом уровне:

  • Stratum 1 — 2 сервера с GPS-приёмниками и PPS (Pulse Per Second) сигналом. Точность ±1 мкс. Размещены в двух ЦОД банка.
  • Stratum 2 — 4 сервера chrony, синхронизированные с нашими S1 и резервными источниками (ВНИИФТРИ, МСК-IX). Точность ±100 мкс. По 2 в каждом ЦОД.
  • Stratum 3 — все 340 серверов банка, синхронизирующиеся только с внутренними S2. Точность ±1 мс.

Ключевой принцип: ни один продуктивный сервер не обращается к внешним NTP-источникам напрямую. Это изолирует инфраструктуру от проблем публичного NTP Pool и уменьшает поверхность атаки (NTP amplification).

# Топология NTP-инфраструктуры ФинансБанк
#
#  [GPS/PPS] ──→ [S1-DC1]     [GPS/PPS] ──→ [S1-DC2]
#                  │ \                          │ \
#            ┌─────┘  └────┐              ┌─────┘  └────┐
#         [S2-DC1-A]  [S2-DC1-B]      [S2-DC2-A]  [S2-DC2-B]
#            │             │              │             │
#       ┌────┴────┐   ┌────┴────┐    ┌────┴────┐   ┌────┴────┐
#     [srv1] [srv2] [srv3] [srv4]  [srv5] [srv6] [srv7] [srv8]
#                   ... 340 серверов ...

Stratum 1: GPS-приёмник и PPS-дисциплина

Для Stratum 1 мы использовали серверы с GPS-приёмниками u-blox ZED-F9T, подключёнными через USB с выведенным PPS-сигналом на GPIO. PPS обеспечивает точность до 50 наносекунд — на порядки лучше, чем сетевой NTP.

# Установка и настройка gpsd для GPS-приёмника
sudo apt install gpsd gpsd-clients chrony

# /etc/default/gpsd
DEVICES="/dev/ttyACM0"
GPSD_OPTIONS="-n -b"
START_DAEMON="true"

# Проверка работы GPS:
gpsmon /dev/ttyACM0
# Должны видеть координаты и количество спутников (минимум 4)
# /etc/chrony/chrony.conf на Stratum 1 сервере

# GPS через shared memory (NMEA — грубое время)
refclock SHM 0 refid GPS precision 1e-1 offset 0.0 delay 0.2 noselect

# PPS через /dev/pps0 — точное время (наносекундная точность)
refclock PPS /dev/pps0 refid PPS precision 1e-9 lock GPS prefer

# Резервные внешние источники на случай потери GPS-сигнала
server ntp1.vniiftri.ru iburst minpoll 6 maxpoll 10
server ntp2.vniiftri.ru iburst minpoll 6 maxpoll 10
server ntp.msk-ix.ru iburst minpoll 6 maxpoll 10

# Раздача времени внутренним S2 серверам
allow 10.100.0.0/16

# Защита от DDoS — ограничение запросов
ratelimit interval 1 burst 16 leak 2

# Логирование drift для мониторинга
driftfile /var/lib/chrony/drift
logdir /var/log/chrony
log tracking measurements statistics

# Аппаратный timestamping для минимальной задержки
hwtimestamp eth0
# Проверка состояния после запуска:
sudo chronyc sources -v
# MS Name/IP address     Stratum Poll Reach LastRx Last sample
# #* PPS                       0   4   377     5   +12ns[ +15ns] +/-  103ns
# #? GPS                       0   4   377     5   -45ms[ -45ms] +/-  200ms
# ^- ntp1.vniiftri.ru          1  10   377   512   +245us[+245us] +/-   12ms

# PPS (*) выбран как основной источник с точностью ±103 ns

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

Stratum 2: chrony с высокой доступностью

Серверы Stratum 2 — основная рабочая лошадка инфраструктуры. Они принимают время от S1 и раздают 340 клиентам.

# /etc/chrony/chrony.conf на Stratum 2 сервере (DC1-A)

# Источники времени — оба наших S1 + резервные
server 10.100.1.1 iburst minpoll 4 maxpoll 6 prefer  # S1-DC1 (приоритет)
server 10.100.2.1 iburst minpoll 4 maxpoll 6          # S1-DC2
server ntp1.vniiftri.ru iburst minpoll 8 maxpoll 12   # Резерв
server ntp.msk-ix.ru iburst minpoll 8 maxpoll 12      # Резерв

# Раздача времени клиентам
allow 10.0.0.0/8

# Более агрессивный ratelimit — S2 принимают основную нагрузку
ratelimit interval 1 burst 32 leak 4

# Быстрая первичная синхронизация
makestep 0.1 3

# Аппаратный timestamping
hwtimestamp eth0

driftfile /var/lib/chrony/drift
logdir /var/log/chrony
log tracking measurements statistics
# Конфигурация клиентов (все 340 серверов банка)
# /etc/chrony/chrony.conf

# Четыре S2 сервера для отказоустойчивости
server 10.100.1.10 iburst minpoll 6 maxpoll 8  # S2-DC1-A
server 10.100.1.11 iburst minpoll 6 maxpoll 8  # S2-DC1-B
server 10.100.2.10 iburst minpoll 6 maxpoll 8  # S2-DC2-A
server 10.100.2.11 iburst minpoll 6 maxpoll 8  # S2-DC2-B

# Корректировка времени без прыжка (для БД и Kerberos)
makestep 0.01 3
maxchange 1.0 1 2

# Запрет раздачи времени другим
port 0

driftfile /var/lib/chrony/drift

Параметр maxchange 1.0 1 2 — страховка от ложной коррекции: если источник вдруг покажет скачок больше 1 секунды, chrony остановится и подаст сигнал в мониторинг, а не сдвинет часы на всех серверах банка.

Мониторинг: Prometheus ntp_exporter

Мониторинг NTP — не опция, а обязательное требование PCI DSS. Мы развернули ntp_exporter для Prometheus на каждом S2-сервере и выборочно на клиентах:

# Установка ntp_exporter
wget https://github.com/sapcc/ntp_exporter/releases/download/v2.1.0/ntp_exporter-2.1.0.linux-amd64.tar.gz
tar xzf ntp_exporter-2.1.0.linux-amd64.tar.gz
sudo mv ntp_exporter /usr/local/bin/

# systemd unit
# /etc/systemd/system/ntp-exporter.service
[Unit]
Description=NTP Exporter for Prometheus
After=network.target

[Service]
ExecStart=/usr/local/bin/ntp_exporter \
  --ntp.server=127.0.0.1 \
  --web.listen-address=:9559
Restart=always
User=ntp_exporter

[Install]
WantedBy=multi-user.target
# Prometheus scrape config
- job_name: 'ntp'
  scrape_interval: 30s
  static_configs:
    - targets:
      - 's1-dc1:9559'
      - 's1-dc2:9559'
      - 's2-dc1-a:9559'
      - 's2-dc1-b:9559'
      - 's2-dc2-a:9559'
      - 's2-dc2-b:9559'
  relabel_configs:
    - source_labels: [__address__]
      target_label: instance
# Alertmanager rules — алерты по NTP
groups:
  - name: ntp_alerts
    rules:
      - alert: NTPOffsetCritical
        expr: abs(ntp_offset_seconds) > 0.1
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "NTP offset > 100ms на {{ $labels.instance }}"
          description: "Текущий offset: {{ $value }}s. PCI DSS требует < 1s."

      - alert: NTPStratumDegraded
        expr: ntp_stratum > 3
        for: 10m
        labels:
          severity: warning
        annotations:
          summary: "NTP stratum деградировал до {{ $value }} на {{ $labels.instance }}"

      - alert: NTPServerUnreachable
        expr: ntp_sanity == 0
        for: 5m
        labels:
          severity: critical
        annotations:
          summary: "NTP-сервер недоступен на {{ $labels.instance }}"

В Grafana мы создали дашборд с визуализацией: offset каждого сервера (должен быть <1 мс), stratum level, jitter, reach (показатель доступности источника). Любое отклонение от нормы генерирует алерт в Telegram-канал дежурной смены.

Chrony vs ntpd: почему мы выбрали chrony

Банк ранее использовал ntpd (классический NTP-демон). Мы мигрировали все серверы на chrony, и вот почему:

Параметрntpdchrony
Первичная синхронизация5-10 минутСекунды (iburst)
Работа на виртуальных машинахПлохо (drift при паузе VM)Отлично (компенсирует скачки)
Аппаратный timestampingНетДа (hwtimestamp)
Потребление памяти~12 MB~4 MB
Поддержка PPSЧерез сложную конфигурациюВстроенная (refclock PPS)
Режим offlineНет (теряет время)Да (экстраполяция drift)
Безопасность (NTS)НетДа (Network Time Security)

Критический аргумент для банка: chrony корректно работает на виртуальных машинах. При миграции VM между гипервизорами ntpd мог потерять синхронизацию на минуты, chrony восстанавливается за секунды благодаря алгоритму компенсации drift.

# Миграция с ntpd на chrony (выполнялась через Ansible на 340 серверах)
---
- name: Migrate ntpd to chrony
  hosts: all_servers
  become: yes
  tasks:
    - name: Stop and disable ntpd
      systemd:
        name: ntp
        state: stopped
        enabled: no
      ignore_errors: yes

    - name: Remove ntpd
      apt:
        name: [ntp, ntpdate]
        state: absent

    - name: Install chrony
      apt:
        name: chrony
        state: present

    - name: Deploy chrony config
      template:
        src: chrony.conf.j2
        dest: /etc/chrony/chrony.conf
      notify: restart chrony

    - name: Enable and start chrony
      systemd:
        name: chrony
        state: started
        enabled: yes

  handlers:
    - name: restart chrony
      systemd:
        name: chrony
        state: restarted

Результаты и соответствие PCI DSS

Через 2 недели после внедрения мы провели повторный аудит NTP-инфраструктуры:

МетрикаДо проектаПосле проекта
Максимальный offset между серверами15 секунд0.8 мс
Средний offset2.3 секунды0.12 мс
Stratum уровень клиентов4-6 (нестабильно)3 (стабильно)
Доступность NTP-сервиса~95% (падения pool.ntp.org)99.99% (внутренняя инфра)
Время восстановления синхронизации5-10 минут3-5 секунд
PCI DSS 10.4 complianceНе соответствуетПолное соответствие

Побочные эффекты: Kerberos-аутентификация перестала «отваливаться», корреляция логов в SIEM работает корректно, биржевые ордера исполняются в правильном порядке. Подробнее о построении отказоустойчивых сетевых сервисов — на itfresh.ru.

Часто задаваемые вопросы

GPS даёт автономность: даже при полном отключении интернета (DDoS, авария магистрали) банк продолжает иметь точное время. Для PCI DSS это требование непрерывности. Кроме того, GPS+PPS даёт точность ±50 нс против ±10 мс у сетевого NTP — на два порядка лучше.
Катастрофа 2024 года показала: в российской зоне NTP Pool из 140 серверов за две недели осталось 4. Публичные пулы не гарантируют SLA. Для банка с требованиями PCI DSS единственный надёжный вариант — собственная Stratum-иерархия с контролируемыми источниками.
Hardware timestamping — это фиксация времени прибытия NTP-пакета сетевой картой, а не ядром ОС. Разница: ядро добавляет 50-200 мкс задержки из-за обработки в стеке TCP/IP, аппаратный timestamp точен до 100 нс. Для Stratum 1-2 серверов это обязательно, для клиентов — необязательно.
Три уровня: ratelimit в chrony (ограничение запросов с одного IP), firewall (NTP-порт 123/UDP открыт только для внутренних подсетей), мониторинг трафика (алерт при аномальном количестве NTP-запросов — признак amplification-атаки). Для продвинутой защиты — NTS (Network Time Security) в chrony.
Нет. Stratum 1 с GPS/PPS требует прямого доступа к аппаратному прерыванию PPS и минимальной задержки ядра. Гипервизор добавляет недетерминированную задержку в сотни микросекунд. Stratum 1 — всегда bare metal. Stratum 2 и ниже — можно на VM, chrony корректно компенсирует drift виртуализации.

Нужна помощь с проектом?

Специалисты АйТи Фреш помогут с архитектурой, DevOps, безопасностью и разработкой — 15+ лет опыта

📞 Связаться с нами
#NTP синхронизация времени#chrony настройка#GPS PPS источник времени#stratum иерархия NTP#PCI DSS требования время#ntp_exporter prometheus#корпоративный NTP сервер#Kerberos время синхронизация
Комментарии 0

Оставить комментарий

загрузка...