Машинный перевод, не проверенный носителем языка. Эталоном служит английская версия.

Доверие к приёмнику и морская отрасльПравить на GitHubИсточник: docs/TRUST-TELEMETRY.md

Доверие к GNSS как телеметрия безопасности

kshana trust-telemetry превращает поток доверия к GNSS по эпохам (оценка 0–100, диапазон, причины) в сигналы, которые центр эксплуатации или безопасности уже принимает: метрики Prometheus, события syslog в CEF или LEEF для SIEM и, по желанию, OpenTelemetry. Он читает поток; он никогда не изменяет оценку доверия и не передаёт ничего, кроме телеметрии.

Один результат оценки доверия в трёх форматах экспорта по реальным прогонам движка v0.40.0 (`kshana trust-telemetry`) на examples/maritime-trust: текстовая выдача Prometheus (последняя оценка доверия равна 5,9, установлена полоса недоверия) и последние сообщения CEF и LEEF. Команда ничего не публикует, пока не задан адрес назначения, не хранит учётных данных и не излучает радиосигнал. Программное обеспечение консультативного характера, не навигационное оборудование с утверждённым типом (IEC 61108, IEC 61162): ответственность за судовождение остаётся на операторе.Один результат оценки доверия в трёх форматах экспорта по реальным прогонам движка v0.40.0 (`kshana trust-telemetry`) на examples/maritime-trust: текстовая выдача Prometheus (последняя оценка доверия равна 5,9, установлена полоса недоверия) и последние сообщения CEF и LEEF. Команда ничего не публикует, пока не задан адрес назначения, не хранит учётных данных и не излучает радиосигнал. Программное обеспечение консультативного характера, не навигационное оборудование с утверждённым типом (IEC 61108, IEC 61162): ответственность за судовождение остаётся на операторе.

Запустите#

# live stream on stdin -> /metrics on localhost:9464
kshana receiver-trust live <args> | kshana trust-telemetry

# replay a batch result (the score is the epoch's own for a vessel platform, absent otherwise)
kshana trust-telemetry --result session.result.json --print-metrics
kshana trust-telemetry --result session.result.json --print-syslog --format leef

# SIEM over UDP, one event per band change
kshana trust-telemetry --input stream.jsonl --syslog-udp siem.example:514 --format cef --host ops-gw1

Вход — это живая схема JSON-строк v1.1, описанная в docs/MARITIME-TRUST.md. Читаются: t_s; state (calibrating|nominal|degraded|untrusted, диапазон); score (0–100 или null); time (время эпохи, как оно указано); gate (off|passed|withheld); position (lat_deg, lon_deg, height_m или null); причины — это мониторы в deductions, затем любые дополнительные в alarms; начиная со схемы 1,3, geometry (status, hdop, pdop, n_used) и class каждого вычета. Остальные ключи игнорируются, так как схема растёт только добавлением ключей. Строка, которая не разбирается, учитывается в kshana_trust_input_errors_total и пропускается; оценки вне диапазона 0–100 отклоняются, а не обрезаются, чтобы изменение формата не прошло незамеченным. Единственный код, знающий этот формат, — src/telemetry/sample.rs.

/metrics отдаётся без аутентификации и по умолчанию привязан к 127.0.0.1:9464. Привязка к другому адресу выводит предупреждение; поставьте его за собственное управление доступом. Конечная точка обслуживает одно соединение за раз с ограничением чтения 2 с, поэтому простаивающий клиент может задержать сбор данных на это время; она рассчитана на один сборщик, а не на открытую сеть.

Home Assistant и устройства NTP (MQTT)#

--print-mqtt выводит, а --mqtt-tcp <host:port> публикует документ состояния JSON и сообщения обнаружения Home Assistant по MQTT. Обнаружение (с удержанием, под homeassistant/...) создаёт три сущности: оценка доверия, диапазон доверия (с причинами в виде атрибутов) и датчик проблемы untrusted. Документ состояния отправляется в <prefix>/state (по умолчанию kshana/trust/state, с удержанием): state, score (null, пока её нет), untrusted, t_s, time, reasons, gate и заявление консультативного характера; положение никогда не включается. Параметры: --mqtt-prefix, --mqtt-node, --mqtt-discovery.

Издатель говорит по MQTT 3.1.1 с QoS 0 и читает только CONNACK брокера. У него нет учётных данных и нет TLS, поэтому используйте брокер в локальной сети (или локальный ретранслятор, который их добавляет). Доставка идёт в собственном потоке за очередью из 1024 сообщений: неработающий брокер приводит к потере сообщений, которые учитываются и сообщаются в конце и никогда не останавливают поток. Устройство NTP или любой другой потребитель, которому нужен простой JSON, может читать ту же строку состояния. Приёмнику или часам ничего не записывается. Python, WebAssembly и MCP принимают format = "mqtt" и возвращают те же строки topic<TAB>payload (там ничего не публикуется).

Из Python, WebAssembly и MCP#

Кодировщики также доступны как вызовы «текст на входе — текст на выходе» без процесса, сокета и часов: Python kshana.trust_telemetry(input, format, host="", input_kind="jsonl", expose_position=False, syslog_all=False, unix_nano=0), экспорт WebAssembly trust_telemetry(input, format, host, input_kind, options_json) и инструмент MCP trust_telemetry (команда плагина /kshana-trust-telemetry). format — это prometheus, cef, leef или otlp; input_kind — это jsonl (поток) или result (результат пакета). Они возвращают тот же текст, что печатает командная строка (--print-metrics, --print-syslog), с теми же ограничениями: строки syslog не несут метки времени, host — не более 255 печатаемых символов ASCII без пробелов (иначе отклоняется, здесь и в командной строке), а ответ, превышающий предел поверхности (4 МиБ в MCP), отклоняется, потому что CEF и LEEF с syslog_all записывают одно событие на эпоху. Ничего не отправляется, не обслуживается и не записывается; работающие экспортёры остаются процессом в командной строке.

Доставка никогда не останавливает оценку#

Доставка syslog и OpenTelemetry идёт в собственных потоках. Цикл приёма только передаёт им сообщение или снимок и никогда не ждёт, поэтому неработающий, медленный или нечитающий сборщик не может создать обратное давление на живой поток или заморозить /metrics:

  • у каждого соединения и каждой записи есть ограничение 2 с; неудавшееся соединение отбрасывается и лениво устанавливается заново с экспоненциальной задержкой от 1 с до 60 с;
  • сообщение, которое не удаётся доставить (сборщик недоступен, истекло время записи, очередь из 1024 заполнена), отбрасывается и учитывается в kshana_trust_syslog_send_failures_total; настройте оповещение по его частоте;
  • экспортёру OpenTelemetry передаётся копия реестра, поэтому во время сетевого ввода-вывода блокировка не удерживается; если экспорт ещё выполняется, новый снимок пропускается (следующий несёт те же накопленные итоги).

В конце ввода потокам отправки даётся оставшееся время на завершение.

Метрики Prometheus#

Метрика Тип Метки Значение
kshana_build_info gauge version константа 1
kshana_trust_score gauge последняя оценка 0–100; отсутствует, если источник её не даёт
kshana_trust_band gauge band 1 для текущего диапазона, 0 для остальных
kshana_trust_gate gauge gate off, passed, withheld, unknown: 1 для текущего состояния, 0 для остальных; отсутствует без шлюза
kshana_trust_position_latitude_degrees, ..._longitude_degrees, ..._height_meters gauge положение, сообщённое приёмником; только с --expose-position (конечная точка не аутентифицирована, а положение может выдать площадку или судно)
kshana_trust_reason_active gauge reason 1, если присутствует в последней эпохе
kshana_trust_epochs_total counter band принятые эпохи
kshana_trust_reason_epochs_total counter reason эпохи, в которых присутствовала причина
kshana_trust_input_errors_total counter строки ввода, которые не удалось разобрать
kshana_trust_reason_overflow_total counter вхождения причин, свёрнутые в reason="other" (см. ниже)
kshana_trust_syslog_send_failures_total counter события syslog, которые не доставлены
kshana_trust_epoch_offset_seconds gauge смещение последней эпохи от начала потока
kshana_trust_last_sample_timestamp_seconds gauge время получения по настенным часам; настройте оповещение по его возрасту
kshana_trust_geometry gauge status геометрия спутников в последней эпохе, good, degraded, unknown: 1 для текущей (входные данные схемы 1,3)
kshana_trust_geometry_degraded gauge 1 ухудшена, 0 хороша; отсутствует, когда геометрия неизвестна (1.3)
kshana_trust_geometry_signal_loss gauge 1 когда видимые спутники не отслеживаются, хотя их геометрия хороша (потерян сигнал, а не небо; geometry_degraded по-прежнему равна 1), иначе 0; отсутствует, когда геометрия неизвестна или вход этого не сообщает (1.3)
kshana_trust_geometry_hdop, ..._pdop, ..._used_satellites gauge HDOP, PDOP и число используемых спутников в последней эпохе; каждая отсутствует, если её нет (1.3)
kshana_trust_geometry_epochs_total counter status эпохи по статусу геометрии (1.3)
kshana_trust_geometry_label gauge label метка геометрии в последней эпохе, good, fair, poor, unknown: 1 для текущей; никогда не оценивается (оценка снижается только за poor); из входных данных, несущих метку (0,36)
kshana_trust_geometry_vdop gauge VDOP в последней эпохе; отсутствует, если его нет (0.36)

Главное — метка геометрии. Стройте графики и настраивайте оповещения по kshana_trust_geometry_label (OTLP kshana.geometry.label, в CEF третье поле cs6, в LEEF geoLabel): poor — единственная метка, за которую оценка снижается. Статус геометрии носит описательный характер: degraded включает информационный случай sky-blocked, который может сопровождаться хорошим или удовлетворительным DOP, поэтому не поднимайте тревогу только по kshana_trust_geometry_degraded.

Начиная со входных данных схемы 1,3, kshana_trust_reason_active также несёт метку class (geometry, environment, inconsistency) у каждой причины, которая её имела: класс вычета в последней эпохе. Ряды геометрии идут после всех остальных и только когда входная эпоха несёт geometry (живая схема 1,3, результат движка 0,36 или новее), поэтому поток или результат 0,35 отображается байт в байт как прежде. Значения меток — фиксированные наборы (неизвестный статус читается как unknown; неизвестный класс отбрасывается). Настраивайте оповещение по kshana_trust_reason_active{class="inconsistency"}, а не только по диапазону, чтобы плохое небо не поднимало тревогу как атака; класс geometry — это утверждение о небе, а не вывод о том, что атаки не было (см. docs/RECEIVER-TRUST.md).

Метка class входит в идентичность ряда: когда класс причины меняется между эпохами (loss-of-lock с environment на geometry, если потерянные спутники были низкими, или geometry на inconsistency, если заявленный HDOP расходится с заявленным небом), старый ряд больше не экспортируется и начинается новый. Запрашивайте по reason с max by (reason), когда класс не важен, и ожидайте, что такая смена будет выглядеть как окончание одного ряда и начало другого. Ряды схемы 1,3, метка class и поля геометрии CEF/LEEF проверяются собственными тестами движка и оракулами CEF (pycef, Logstash); у внешних оракулов Prometheus и OTLP потока 1,3 пока нет.

Названия причин обрезаются до 128 символов, и не более 64 различных причин получают собственный ряд; последующие учитываются в reason="other" и в kshana_trust_reason_overflow_total, поэтому враждебный или ошибочный ввод не может создать неограниченное число значений метки.

band — одно из calibrating, nominal, degraded, untrusted, unknown. Названия причин — это названия мониторов потока (kinematic, heading-course, ...; для результата пакета cn0-drop, agc, raim).

Образец панели находится в deploy/grafana/kshana-gnss-trust.json (импортируйте его и выберите свой источник данных Prometheus).

Syslog: CEF и LEEF#

События отправляются в оболочке RFC 5424 (facility local0, приложение kshana, идентификатор сообщения GNSSTRUST) по UDP (по одной датаграмме на событие; IPv4 или IPv6) или TCP, по умолчанию с завершением переводом строки или, с --syslog-octet-counting, с кадрированием <length> <message> по RFC 6587. По умолчанию на каждое изменение диапазона отправляется одно событие; --syslog-all отправляет по одному на эпоху. Поставщик записывается как Ashforde OU (ASCII), чтобы ни один SIEM не декодировал его неверно.

Понятие Серьёзность syslog Серьёзность CEF LEEF sev
calibrating 6 info 0 1
штатный 6 info 1 1
ухудшены 4 warning 5 5
untrusted 2 critical 9 9
unknown 5 notice 3 3

Сопоставление полей (идентификатор события — gnss-trust.<band>):

Значение CEF LEEF 2,0 (разделитель ^)
категория cat=gnss-trust cat
хост отправки dvchost devHost
диапазон cs1 (метка band) band
причины, через запятую cs2 (reasons) reasons
предыдущий диапазон cs3 (previousBand) previousBand
оценка cfp1 (trustScore), пропускается, если её нет trustScore
смещение эпохи, с cfp2 (epochOffsetSeconds) epochOffsetSeconds
метка времени журнала cs4 (logTime) logTime
состояние шлюза cs5 (gate) gate
статус геометрии, затем ; и классы вычетов эпохи, через запятую (например, degraded;environment,geometry) (входные данные 1,3); из входных данных, несущих метку (0,36), третье поле, ; и метка, причём поле классов тогда присутствует всегда (например, degraded;;poor, good;;fair) cs6 (geometry) geoStatus (только статус), geoClass (классы) и geoLabel (метка)
HDOP (1.3) cfp3 (geometryHdop) geoHdop
PDOP (1.3) cfp4 (geometryPdop) geoPdop (0,36, с меткой)
VDOP (0,36, с меткой) не передаётся: используются четыре пользовательских поля с плавающей запятой geoVdop
используемые спутники (0,36, с меткой) cn1 (geometryUsedSatellites), целое число geoUsed
потеря сигнала: видимые спутники не отслеживаются, хотя их геометрия хороша (1.3) не передаётся как поле (в словаре CEF нет свободного ключа для него): статус читается как degraded, а класс вычета геометрии environment — в cs6 geoSignalLoss=1, только пока это верно

В CEF геометрия использует только пользовательские поля словаря (никаких выдуманных ключей); метка передаётся в cs6, а не в flexString1, потому что кодек CEF Logstash не сопоставляет поля flexString. События геометрии 1,3, включая случаи с меткой, входят в строку CEF с уровнем VALIDATED: оба разборщика-оракула читают их обратно как записано (tests/cef_reference.rs, поправки 4 и 5, каждая зарегистрирована до того, как какой-либо из разборщиков был запущен на её случаях). Поля метки, VDOP и числа спутников добавляются после каждого более раннего поля и ряда и только для входных данных, несущих метку, поэтому вход без неё отображается точно как прежде.

Пустые поля опускаются (без cs2= при отсутствии причин). Имя хоста обрезается до 255 символов. Значения заголовка CEF экранируют \ и |; значения расширения экранируют \, = и переводы строк. В значениях LEEF ^ и переводы строк заменяются пробелами.

OpenTelemetry (по умолчанию выключен)#

Соберите с --features otlp и передайте --otlp http://host:4318/v1/metrics. Экспортёр отправляет OTLP/HTTP JSON (kshana.trust.score, kshana.trust.band, kshana.trust.epochs, kshana.trust.reason.epochs, а для входных данных схемы 1,3 — kshana.geometry.status, kshana.geometry.degraded, kshana.geometry.signal_loss, kshana.geometry.hdop, kshana.geometry.pdop, kshana.geometry.used_satellites и, из входных данных, несущих метку (0,36), kshana.geometry.label (атрибут label) и kshana.geometry.vdop; накопленные суммы несут startTimeUnixNano) каждые --otlp-every эпох (по умолчанию 10) и в конце ввода. Он не добавляет зависимостей и не имеет TLS: отправляйте на сборщик на том же хосте или в доверенном сегменте, который передаёт данные дальше по TLS. Конечные точки https:// отклоняются.