Реконструкция инцидента развалилась: в логах не оказалось смещения часового пояса
Восстановление хронологии инцидента обычно кажется почти механической задачей. Нужно собрать записи с веб-сервера, балансировщика, приложения и почтового шлюза, отсортировать их по времени и определить, какое событие произошло раньше. Однако на практике такая схема быстро перестаёт работать: ответ может оказаться раньше запроса, закрытие сессии - предшествовать её созданию, а письмо - быть доставленным за несколько часов до отправки.
При этом в самих логах не обязательно будет техническая ошибка. Каждый компонент мог корректно записать собственные события - просто использовал свои часы, формат времени или момент фиксации записи. Именно поэтому анализ логов сервера нельзя сводить к простой сортировке строк.
Почему временная шкала начинает противоречить сама себе
Обычно расхождения объясняются тремя причинами. Первая - дрейф системных часов. Если узел не синхронизируется с эталонным временем, его часы постепенно уходят вперёд или назад. Даже несколько секунд в сутки за месяц превращаются в заметную погрешность. Для расследования, где важно понять последовательность "получен запрос - запущен процесс - отправлен ответ", этого уже достаточно, чтобы поменять события местами.
Вторая причина - разные точки отсчёта. Один сервер пишет время в UTC, другой использует локальный часовой пояс, третий наследует настройки контейнера или виртуальной машины. При этом часы на всех узлах могут быть абсолютно исправны: проблема заключается не в точности, а в несопоставимости чисел.
Третий вариант наиболее коварен: в журнал попадает не время события, а момент его записи в лог. Между возникновением события и доставкой сообщения в систему журналирования могут пройти миллисекунды, секунды и даже минуты. Буферизация, очереди, сетевые сбои и повторная отправка делают такую задержку непостоянной.
Первую проблему решают синхронизацией, вторую - единым и полным форматом временных меток, а третью - пониманием того, какое именно время зафиксировано в конкретной записи: время возникновения, получения, обработки или сохранения.
Почему часовой пояс должен быть указан явно
Классический BSD-syslog, описанный в RFC 3164, выглядит привычно, но содержит критический недостаток: в записи нет года и часового смещения. Год приходится восстанавливать по имени файла, периоду ротации или соседним сообщениям. Часовой пояс определить ещё сложнее - для этого нужно знать настройки узла, который создал запись. Если сервер уже выведен из эксплуатации, такая информация может быть безвозвратно потеряна.
Более современный RFC 5424 предусматривает полноценную временную метку: год, доли секунды и смещение относительно UTC. Например, суффикс `+05:00` - это не декоративная часть строки, а обязательный элемент, делающий время самодостаточным. Запись с таким обозначением можно корректно нормализовать даже без доступа к исходному серверу.
Практические аспекты построения надёжной временной шкалы и обработки разнородных журналов подробно разобраны в материале о [корреляции логов систем](https://habr.com/ru/articles/1076436/?utm_campaign=1076436&utm_source=habrahabr&utm_medium=rss). Такой подход особенно важен, когда расследование объединяет внутренние события с данными внешних сервисов.
Почему одного UTC недостаточно
Рекомендация хранить данные в UTC правильна, но она касается прежде всего систем, которыми организация управляет самостоятельно. В реальном расследовании часто участвуют внешние источники: заголовки электронных писем, журналы облачного провайдера, выгрузки из SaaS-панели, данные подрядчиков и скриншоты пользовательских интерфейсов.
В заголовке письма обычно указывается смещение отправителя, а не получателя. Внешний провайдер может прислать журнал в собственном часовом поясе. SaaS-система иногда формирует экспорт с учётом настроек аккаунта человека, который нажал кнопку выгрузки. При повторном экспорте другим сотрудником те же события могут получить другие числовые значения. Скриншот же чаще всего показывает локальное время браузера того, кто его сделал.
Поэтому нормализация должна выполняться при поступлении данных в систему сбора и анализа логов. В этот момент ещё известны происхождение сообщения, его транспорт, настройки интеграции и исходный формат. Позже восстановить контекст может быть невозможно.
Отдельная проблема - переход на летнее время. В период обратного перевода часов один и тот же локальный час повторяется дважды. Если в записи нет смещения, два разных момента получают одинаковую метку, а сортировка событий внутри этого интервала становится предположением.
Синхронизация службы не равна синхронизации часов
На серверах часто установлен NTP-клиент, а соответствующая служба автоматически запускается вместе с системой. Но сам факт запуска ещё не означает, что узел действительно получил корректное время. Сервер синхронизации может быть недоступен месяцами, а служба при этом продолжит считаться работающей.
В системах с systemd полезно различать два состояния:
- `NTP=yes` - механизм синхронизации включён;
- `NTPSynchronized=yes` - система действительно синхронизировала часы.
Это независимые утверждения, поэтому мониторить следует именно второе. При этом проверка зависит от используемого инструмента. Для `chrony` нужно анализировать вывод `chronyc tracking`, а для `ntpd` - его собственные диагностические показатели. Иначе исправный сервер можно ошибочно признать неисправным.
Есть и дополнительная оговорка: флаг синхронизации ядра не всегда сбрасывается немедленно после потери связи с сервером времени. Поэтому одного разового теста недостаточно. Надёжнее контролировать успешные обмены, величину поправки, последний ответ от источника времени и доступность нескольких NTP-серверов.
Что проверить до расследования
Надёжная реконструкция начинается задолго до инцидента. В каждой системе следует заранее определить, какие поля обязательны для журнала: идентификатор запроса, идентификатор сессии, имя узла, тип события, время возникновения и время доставки в систему сбора. Если приложение отправляет данные асинхронно, эти моменты желательно хранить раздельно.
Не менее важно регулярно тестировать задержку доставки логов. Даже при идеальной синхронизации серверов записи могут поступать в неправильном порядке из-за очередей и сетевых разрывов. Система корреляции должна уметь учитывать допустимое окно задержки и не делать выводы только на основании времени поступления.
Полезно сохранять исходную временную метку вместе с нормализованной. Тогда аналитик сможет понять, какой часовой пояс использовался первоначально, кто выполнил преобразование и не была ли запись изменена при импорте. Для критичных журналов стоит включать контроль целостности, длительное хранение и резервную копию отдельно от основной инфраструктуры.
В системах, где требуется точное измерение интервалов, также необходимо различать `CLOCK_REALTIME` и `CLOCK_MONOTONIC`. Первый отражает календарное время и может изменяться после синхронизации или ручной корректировки. Второй предназначен для измерения длительности и не должен "прыгать" назад при переводе часов. Поэтому для ответа на вопрос "сколько выполнялась операция" корректнее использовать монотонные часы, а для связи события с внешним журналом - календарную метку с часовым поясом.
Минимальный стандарт для логирования
Каждая запись, используемая в расследовании инцидентов информационной безопасности, должна по возможности содержать полный timestamp с часовым смещением, точность не ниже миллисекунд, имя источника, уникальный идентификатор события и признак того, когда именно была создана метка.
На стороне платформы стоит внедрить единый формат обмена, автоматическую проверку состояния NTP или chrony, контроль задержки доставки и оповещения о существенном дрейфе часов. Отдельно нужно документировать настройки внешних интеграций: часовой пояс, формат экспорта, правила округления и поведение при повторной отправке.
Только совокупность этих мер делает мониторинг и анализ событий безопасности действительно полезным. Иначе даже большое хранилище журналов превращается в набор частично несовместимых свидетельств, на основании которых невозможно уверенно восстановить последовательность атаки или сбоя.


