Traducción automática, no revisada por un hablante nativo. El inglés es la referencia.

Confianza del receptor y ámbito marítimoEditar en GitHubFuente: docs/TRUST-TELEMETRY.md

Confianza en GNSS como telemetría de seguridad

kshana trust-telemetry convierte el flujo de confianza GNSS por época (puntuación de 0-100, banda, motivos) en señales que un centro de operaciones o de seguridad ya ingiere: métricas de Prometheus, eventos de syslog en CEF o LEEF para un SIEM y, opcionalmente, OpenTelemetry. Lee el flujo; nunca cambia la evaluación de confianza y no transmite nada salvo telemetría.

Un resultado de confianza en tres formatos de exportación, a partir de ejecuciones reales del motor v0.40.0 (`kshana trust-telemetry`) sobre examples/maritime-trust: exposición de texto de Prometheus (la última puntuación de confianza es 5,9 y la banda de no confiable es la activa), y los últimos mensajes CEF y LEEF. El comando no publica nada si no se le da un destino, no guarda credenciales y no transmite ninguna señal de radio. Software de carácter consultivo, no un equipo de navegación homologado (IEC 61108, IEC 61162): el operador sigue siendo responsable de la navegación del buque.Un resultado de confianza en tres formatos de exportación, a partir de ejecuciones reales del motor v0.40.0 (`kshana trust-telemetry`) sobre examples/maritime-trust: exposición de texto de Prometheus (la última puntuación de confianza es 5,9 y la banda de no confiable es la activa), y los últimos mensajes CEF y LEEF. El comando no publica nada si no se le da un destino, no guarda credenciales y no transmite ninguna señal de radio. Software de carácter consultivo, no un equipo de navegación homologado (IEC 61108, IEC 61162): el operador sigue siendo responsable de la navegación del buque.

Ejecútelo#

# 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

La entrada es el esquema JSON-lines en vivo v1.1 documentado en docs/MARITIME-TRUST.md. Se lee: t_s; state (calibrating|nominal|degraded|untrusted, la banda); score (0-100 o null); time (la hora de la época tal como se declara); gate (off|passed|withheld); position (lat_deg, lon_deg, height_m, o null); los motivos son los monitores de deductions, y luego cualesquiera otros de alarms; a partir del esquema 1,3, geometry (status, hdop, pdop, n_used) y la class de cada deducción. Las demás claves se ignoran, ya que el esquema solo crece añadiendo claves al final. Una línea que no se analiza se cuenta en kshana_trust_input_errors_total y se omite; las puntuaciones fuera de 0-100 se rechazan, no se recortan, de modo que se advierte un cambio de formato. El único código que conoce este formato es src/telemetry/sample.rs.

/metrics se sirve sin autenticación y por defecto en 127.0.0.1:9464. Enlazar a otra dirección imprime una advertencia; póngalo detrás de su propio control de acceso. El punto de conexión atiende una conexión cada vez con un límite de lectura de 2 s, de modo que un cliente inactivo puede retrasar una recolección hasta ese tiempo; está pensado para un único recolector, no para la red abierta.

Home Assistant y dispositivos NTP (MQTT)#

--print-mqtt imprime, y --mqtt-tcp <host:port> publica, un documento de estado JSON y mensajes de descubrimiento MQTT de Home Assistant. El descubrimiento (retenido, bajo homeassistant/...) crea tres entidades: puntuación de confianza, banda de confianza (con los motivos como atributos) y un sensor de problema untrusted. El documento de estado va a <prefix>/state (por defecto kshana/trust/state, retenido): state, score (null mientras no haya ninguna), untrusted, t_s, time, reasons, gate y la declaración orientativa; la posición nunca se incluye. Opciones: --mqtt-prefix, --mqtt-node, --mqtt-discovery.

El publicador habla MQTT 3.1.1 con QoS 0 y solo lee el CONNACK del broker. No tiene credenciales ni TLS, de modo que use un broker de la red local (o un relé local que las añada). La entrega se ejecuta en su propio hilo detrás de una cola de 1024: un broker caído descarta mensajes, que se cuentan y se informan al final, y nunca bloquea el flujo. Un dispositivo NTP o cualquier otro consumidor que quiera JSON simple puede leer la misma línea de estado. No se escribe nada en un receptor ni en un reloj. Python, WebAssembly y MCP admiten format = "mqtt" y devuelven las mismas líneas topic<TAB>payload (allí no se publica nada).

Desde Python, WebAssembly y MCP#

Los codificadores también están disponibles como llamadas de texto de entrada y de salida, sin proceso, socket ni reloj: kshana.trust_telemetry(input, format, host="", input_kind="jsonl", expose_position=False, syslog_all=False, unix_nano=0) de Python, la exportación de WebAssembly trust_telemetry(input, format, host, input_kind, options_json) y la herramienta MCP trust_telemetry (comando del plugin /kshana-trust-telemetry). format es prometheus, cef, leef u otlp; input_kind es jsonl (el flujo) o result (un resultado por lotes). Devuelven el mismo texto que imprime la línea de comandos (--print-metrics, --print-syslog), con los mismos límites: las líneas de syslog no llevan marca de tiempo, host tiene como máximo 255 caracteres ASCII imprimibles sin espacios (se rechaza en caso contrario, aquí y en la línea de comandos), y se rechaza una respuesta mayor que el límite de la superficie (4 MiB en MCP), porque CEF y LEEF con syslog_all escriben un evento por época. No se envía, sirve ni escribe nada; los exportadores en ejecución siguen siendo un proceso de la línea de comandos.

La entrega nunca bloquea la evaluación#

La entrega de syslog y de OpenTelemetry se ejecuta en sus propios hilos. El bucle de ingesta solo les pasa un mensaje o una instantánea y nunca espera, de modo que un colector caído, lento o que no lee no puede ejercer contrapresión sobre el flujo en vivo ni congelar /metrics:

  • cada conexión y cada escritura tiene un límite de 2 s; una conexión fallida se descarta y se reconecta de forma diferida, con retroceso exponencial de 1 s hasta 60 s;
  • un mensaje que no puede entregarse (colector caído, escritura agotada por tiempo, cola de 1024 llena) se descarta y se cuenta en kshana_trust_syslog_send_failures_total; avise según su tasa;
  • al exportador de OpenTelemetry se le entrega una copia del registro, de modo que no se mantiene ningún bloqueo durante la E/S de red; si una exportación sigue en curso, se omite la nueva instantánea (la siguiente lleva los mismos totales acumulados).

Al final de la entrada se da a los hilos emisores el tiempo restante que tienen como límite para terminar.

Métricas de Prometheus#

Métrica Tipo Etiquetas Significado
kshana_build_info gauge version constante 1
kshana_trust_score gauge última puntuación 0-100; ausente si el origen no da ninguna
kshana_trust_band gauge band 1 para la banda actual, 0 para las demás
kshana_trust_gate gauge gate off, passed, withheld, unknown: 1 para el estado actual, 0 para los demás; ausente sin compuerta
kshana_trust_position_latitude_degrees, ..._longitude_degrees, ..._height_meters gauge posición informada por el receptor; solo con --expose-position (el punto de conexión no está autenticado y una posición puede identificar un emplazamiento o un buque)
kshana_trust_reason_active gauge reason 1 si está presente en la última época
kshana_trust_epochs_total contador band épocas recibidas
kshana_trust_reason_epochs_total contador reason épocas en las que el motivo estuvo presente
kshana_trust_input_errors_total contador líneas de entrada que no se pueden analizar
kshana_trust_reason_overflow_total contador apariciones de motivos agrupadas en reason="other" (véase más abajo)
kshana_trust_syslog_send_failures_total contador eventos de syslog no entregados
kshana_trust_epoch_offset_seconds gauge desfase de la última época respecto del inicio del flujo
kshana_trust_last_sample_timestamp_seconds gauge hora de recepción de reloj de pared; avise según su antigüedad
kshana_trust_geometry gauge status geometría de satélites en la última época, good, degraded, unknown: 1 para la actual (entradas del esquema 1,3)
kshana_trust_geometry_degraded gauge 1 degradada, 0 buena; ausente cuando la geometría es desconocida (1.3)
kshana_trust_geometry_signal_loss gauge 1 cuando no se siguen satélites a la vista mientras su geometría es buena (se perdió la señal, no el cielo; geometry_degraded sigue valiendo 1), y 0 en caso contrario; ausente cuando la geometría es desconocida o la entrada no lo indica (1.3)
kshana_trust_geometry_hdop, ..._pdop, ..._used_satellites gauge HDOP, PDOP y satélites usados en la última época; cada uno ausente cuando no hay ninguno (1.3)
kshana_trust_geometry_epochs_total contador status épocas por estado de geometría (1.3)
kshana_trust_geometry_label gauge label etiqueta de geometría en la última época, good, fair, poor, unknown: 1 para la actual; nunca se puntúa (la puntuación solo deduce por poor); a partir de entradas que llevan la etiqueta (0,36)
kshana_trust_geometry_vdop gauge VDOP en la última época; ausente cuando no hay ninguno (0.36)

La etiqueta de geometría es lo principal. Represente y avise según kshana_trust_geometry_label (OTLP kshana.geometry.label, el tercer campo cs6 de CEF, geoLabel de LEEF): poor es la única etiqueta por la que deduce la puntuación. El estado de la geometría es descriptivo: degraded incluye el caso informativo sky-blocked, que puede darse con un DOP bueno o aceptable, de modo que no dé aviso solo por kshana_trust_geometry_degraded.

A partir de las entradas del esquema 1,3, kshana_trust_reason_active lleva además una etiqueta class (geometry, environment, inconsistency) en cada motivo que vino con una: la clase de la deducción en la última época. Las series de geometría van después de todas las demás y solo una vez que una época de entrada lleva geometry (esquema en vivo 1,3, un resultado del motor 0,36 o posterior), de modo que un flujo o resultado 0,35 se representa byte por byte como antes. Los valores de las etiquetas son conjuntos fijos (un estado desconocido se lee unknown; una clase desconocida se descarta). Avise según kshana_trust_reason_active{class="inconsistency"} y no solo según la banda, para que un cielo malo no dé aviso como si fuera un ataque; una clase geometry es una afirmación sobre el cielo, no una constatación de que no hubo ataque (véase docs/RECEIVER-TRUST.md).

La etiqueta class forma parte de la identidad de una serie: cuando la clase de un motivo cambia entre épocas (loss-of-lock de environment a geometry cuando los satélites perdidos estaban bajos, o de geometry a inconsistency cuando el HDOP declarado discrepa del cielo declarado), la serie antigua deja de exportarse y empieza una nueva. Consulte por reason con max by (reason) cuando la clase no importe, y espere que un cambio así parezca una serie que termina y otra que empieza. Las series del esquema 1,3, la etiqueta class y los campos de geometría de CEF/LEEF se comprueban con las propias pruebas del motor y con las referencias independientes de CEF (pycef, Logstash); las referencias independientes externas de Prometheus y de OTLP todavía no tienen ningún flujo 1,3.

Los nombres de motivo se recortan a 128 caracteres, y como máximo 64 motivos distintos reciben su propia serie; los posteriores se cuentan bajo reason="other" y en kshana_trust_reason_overflow_total, de modo que una entrada hostil o con errores no puede crear una cardinalidad de etiquetas ilimitada.

band es una de calibrating, nominal, degraded, untrusted, unknown. Los nombres de motivo son los nombres de monitores del flujo (kinematic, heading-course, ...; para el resultado por lotes, cn0-drop, agc, raim).

Hay un panel de ejemplo en deploy/grafana/kshana-gnss-trust.json (impórtelo y elija su origen de datos de Prometheus).

Syslog: CEF y LEEF#

Los eventos se envían en un sobre RFC 5424 (facility local0, aplicación kshana, identificador de mensaje GNSSTRUST) por UDP (un datagrama cada uno; IPv4 o IPv6) o TCP, terminados en nueva línea por defecto o, con --syslog-octet-counting, enmarcados como <length> <message> según la RFC 6587. Por defecto se envía un evento por cada cambio de banda; --syslog-all envía uno por época. El proveedor se escribe Ashforde OU (ASCII) para que ningún SIEM lo decodifique mal.

Concepto Severidad de syslog Severidad de CEF sev de LEEF
calibrating 6 info 0 1
nominal 6 info 1 1
degradadas 4 warning 5 5
untrusted 2 critical 9 9
unknown 5 notice 3 3

Asignación de campos (el identificador de evento es gnss-trust.<band>):

Significado CEF LEEF 2,0 (delimitador ^)
categoría cat=gnss-trust cat
host emisor dvchost devHost
banda cs1 (etiqueta band) band
motivos, separados por comas cs2 (reasons) reasons
banda anterior cs3 (previousBand) previousBand
puntuación cfp1 (trustScore), se omite si no hay ninguna trustScore
desfase de la época, s cfp2 (epochOffsetSeconds) epochOffsetSeconds
etiqueta de hora del registro cs4 (logTime) logTime
estado de la compuerta cs5 (gate) gate
estado de la geometría, luego ; y las clases de las deducciones de la época, separadas por comas (por ejemplo degraded;environment,geometry) (entradas 1,3); a partir de entradas que llevan la etiqueta (0,36) un tercer campo, ; y la etiqueta, y el campo de clases está entonces siempre presente (por ejemplo degraded;;poor, good;;fair) cs6 (geometry) geoStatus (solo el estado), geoClass (clases) y geoLabel (etiqueta)
HDOP (1.3) cfp3 (geometryHdop) geoHdop
PDOP (1.3) cfp4 (geometryPdop) geoPdop (0,36, con la etiqueta)
VDOP (0,36, con la etiqueta) no se transporta: se ocupan los cuatro campos personalizados de coma flotante geoVdop
satélites usados (0,36, con la etiqueta) cn1 (geometryUsedSatellites), un entero geoUsed
pérdida de señal: satélites a la vista que no se siguen mientras su geometría es buena (1.3) no se transporta como campo (no queda libre ninguna clave del diccionario CEF para ello): el estado indica degraded y la clase de la deducción de geometría, environment, va en cs6 geoSignalLoss=1, solo mientras se da

En CEF, la geometría usa solo campos personalizados del diccionario (sin claves inventadas); la etiqueta va en cs6 en lugar de en flexString1 porque el códec CEF de Logstash no asigna los campos flexString. Los eventos de geometría 1,3, incluidos los casos de etiqueta, forman parte de la fila CEF VALIDATED: ambos analizadores de referencia independiente los leen de nuevo tal como se escribieron (tests/cef_reference.rs, enmiendas 4 y 5, cada una registrada antes de ejecutar cualquiera de los analizadores sobre sus casos). Los campos de etiqueta, VDOP y número de satélites se añaden después de todos los campos y series anteriores, y solo para entradas que llevan la etiqueta, de modo que una entrada sin ella se representa exactamente como antes.

Los campos vacíos se omiten (no hay cs2= sin motivos). El nombre del host se recorta a 255 caracteres. Los valores de la cabecera CEF escapan \ y |; los valores de extensión escapan \, = y los saltos de línea. En los valores LEEF, ^ y los saltos de línea se sustituyen por espacios.

OpenTelemetry (desactivado por defecto)#

Compile con --features otlp y pase --otlp http://host:4318/v1/metrics. El exportador envía por POST JSON de OTLP/HTTP (kshana.trust.score, kshana.trust.band, kshana.trust.epochs, kshana.trust.reason.epochs, y para entradas del esquema 1,3 kshana.geometry.status, kshana.geometry.degraded, kshana.geometry.signal_loss, kshana.geometry.hdop, kshana.geometry.pdop, kshana.geometry.used_satellites y, a partir de entradas que llevan la etiqueta (0,36), kshana.geometry.label (atributo label) y kshana.geometry.vdop; las sumas acumuladas llevan startTimeUnixNano) cada --otlp-every épocas (por defecto 10) y al final de la entrada. No añade ninguna dependencia y no tiene TLS: envíe a un colector en el mismo host o en un segmento de confianza, que reenvíe después por TLS. Los puntos de conexión https:// se rechazan.