Důvěra v GNSS jako bezpečnostní telemetrie
kshana trust-telemetry převádí proud důvěry v GNSS po epochách (skóre 0–100, pásmo, důvody) na signály, které operační nebo bezpečnostní centrum již přijímá: metriky Prometheus, události syslog ve formátu CEF nebo LEEF pro SIEM a volitelně OpenTelemetry. Proud čte; nikdy nemění hodnocení důvěry a nevysílá nic než telemetrii.
Spusťte jej#
# 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
Vstupem je živé schéma JSON-lines v1.1 popsané v docs/MARITIME-TRUST.md. Čte se: t_s; state (calibrating|nominal|degraded|untrusted, pásmo); score (0–100 nebo null); time (čas epochy, jak je uveden); gate (off|passed|withheld); position (lat_deg, lon_deg, height_m nebo null); důvody jsou monitory v deductions, poté další v alarms; od schématu 1,3 geometry (status, hdop, pdop, n_used) a class každého odvození. Ostatní klíče se ignorují, protože schéma roste jen přidanými klíči. Řádek, který se nepodaří zpracovat, se započte do kshana_trust_input_errors_total a přeskočí; skóre mimo 0–100 se odmítají, nikoli ořezávají, aby si změny formátu někdo všiml. Jediný kód, který tento formát zná, je src/telemetry/sample.rs.
/metrics se poskytuje bez autentizace a ve výchozím nastavení naslouchá na 127.0.0.1:9464. Navázání na jinou adresu vypíše varování; zajistěte jej vlastní kontrolou přístupu. Koncový bod obsluhuje vždy jedno spojení s limitem čtení 2 s, takže nečinný klient může zpozdit stažení metrik až o tuto dobu; je určen pro jeden scraper, nikoli pro otevřenou síť.
Zařízení Home Assistant a NTP (MQTT)#
--print-mqtt vypíše a --mqtt-tcp <host:port> publikuje stavový dokument JSON a objevovací zprávy Home Assistant MQTT. Objevování (retained, pod homeassistant/...) vytvoří tři entity: skóre důvěryhodnosti, pásmo důvěryhodnosti (důvody jako atributy) a senzor problému untrusted. Stavový dokument jde na <prefix>/state (výchozí kshana/trust/state, retained): state, score (null, dokud žádné není), untrusted, t_s, time, reasons, gate a poradní prohlášení; poloha není nikdy zahrnuta. Volby: --mqtt-prefix, --mqtt-node, --mqtt-discovery.
Publisher mluví MQTT 3.1.1 s QoS 0 a čte pouze CONNACK od brokeru. Nemá přihlašovací údaje ani TLS, proto použijte broker v místní síti (nebo místní relay, který je doplní). Doručování běží ve vlastním vlákně za frontou o velikosti 1024: nedostupný broker způsobí zahazování zpráv, které se počítají a na konci hlásí, a nikdy nezablokuje proud. NTP zařízení nebo jakýkoli jiný konzument, který chce prostý JSON, může číst stejný stavový řádek. Na přijímač ani na hodiny se nic nezapisuje. Python, WebAssembly a MCP přijímají format = "mqtt" a vracejí stejné řádky topic<TAB>payload (nic se tam nepublikuje).
Z Pythonu, WebAssembly a MCP#
Kodéry jsou dostupné také jako volání typu text na vstupu, text na výstupu, bez procesu, soketu či hodin: Python kshana.trust_telemetry(input, format, host="", input_kind="jsonl", expose_position=False, syslog_all=False, unix_nano=0), export WebAssembly trust_telemetry(input, format, host, input_kind, options_json) a nástroj MCP trust_telemetry (příkaz pluginu /kshana-trust-telemetry). format je prometheus, cef, leef nebo otlp; input_kind je jsonl (proud) nebo result (dávkový výsledek). Vracejí stejný text, jaký vypisuje příkazový řádek (--print-metrics, --print-syslog), se stejnými omezeními: řádky syslogu nenesou časové razítko, host má nejvýše 255 tisknutelných znaků ASCII bez mezer (jinak je odmítnuto, zde i na příkazovém řádku) a odpověď větší než limit dané plochy (4 MiB u MCP) je odmítnuta, protože CEF a LEEF s syslog_all zapisují jednu událost na epochu. Nic se neodesílá, neposkytuje ani nezapisuje; běžící exportéry zůstávají procesem na příkazovém řádku.
Doručování nikdy nezablokuje posouzení#
Doručování syslogu a OpenTelemetry běží ve vlastních vláknech. Vstupní smyčka jim pouze předá zprávu nebo snímek a nikdy nečeká, takže nedostupný, pomalý nebo nečtoucí kolektor nemůže zpětným tlakem zahltit živý proud ani zmrazit /metrics:
- každé připojení a každý zápis mají limit 2 s; neúspěšné spojení se zahodí a znovu naváže líně, s exponenciálním prodlužováním prodlevy od 1 s do 60 s;
- zpráva, kterou nelze doručit (kolektor nedostupný, vypršel časový limit zápisu, fronta o velikosti 1024 plná), se zahodí a započítá do
kshana_trust_syslog_send_failures_total; na její četnost nastavte upozornění; - exportéru OpenTelemetry se předá kopie registru, takže během síťového vstupu a výstupu není držen žádný zámek; pokud export ještě probíhá, nový snímek se přeskočí (další nese stejné kumulativní součty).
Na konci vstupu dostanou odesílací vlákna zbývající čas z jejich limitů na dokončení.
Metriky Prometheus#
| Metrika | Typ | Štítky | Význam |
|---|---|---|---|
kshana_build_info |
gauge | version |
konstanta 1 |
kshana_trust_score |
gauge | poslední skóre 0-100; chybí, pokud zdroj žádné neuvádí | |
kshana_trust_band |
gauge | band |
1 pro aktuální pásmo, 0 pro ostatní |
kshana_trust_gate |
gauge | gate |
off, passed, withheld, unknown: 1 pro aktuální stav, 0 pro ostatní; chybí bez brány |
kshana_trust_position_latitude_degrees, ..._longitude_degrees, ..._height_meters |
gauge | poloha hlášená přijímačem; pouze s --expose-position (koncový bod je bez autentizace a poloha může identifikovat místo nebo plavidlo) |
|
kshana_trust_reason_active |
gauge | reason |
1, pokud byl přítomen v poslední epoše |
kshana_trust_epochs_total |
čítač | band |
přijaté epochy |
kshana_trust_reason_epochs_total |
čítač | reason |
epochy, v nichž byl důvod přítomen |
kshana_trust_input_errors_total |
čítač | nezpracovatelné vstupní řádky | |
kshana_trust_reason_overflow_total |
čítač | výskyty důvodů sloučené do reason="other" (viz níže) |
|
kshana_trust_syslog_send_failures_total |
čítač | nedoručené události syslogu | |
kshana_trust_epoch_offset_seconds |
gauge | odstup poslední epochy od začátku proudu | |
kshana_trust_last_sample_timestamp_seconds |
gauge | čas přijetí podle nástěnných hodin; na jeho stáří nastavte upozornění | |
kshana_trust_geometry |
gauge | status |
geometrie družic v poslední epoše, good, degraded, unknown: 1 pro aktuální (vstupy schématu 1,3) |
kshana_trust_geometry_degraded |
gauge | 1 zhoršená, 0 dobrá; chybí, pokud je geometrie neznámá (1.3) | |
kshana_trust_geometry_signal_loss |
gauge | 1, když družice v dohledu nejsou sledovány, zatímco jejich geometrie je dobrá (ztratil se signál, nikoli obloha; geometry_degraded stále ukazuje 1), jinak 0; chybí, pokud je geometrie neznámá nebo to vstup neuvádí (1.3) |
|
kshana_trust_geometry_hdop, ..._pdop, ..._used_satellites |
gauge | HDOP, PDOP a použité družice v poslední epoše; každá hodnota chybí, pokud žádná není (1.3) | |
kshana_trust_geometry_epochs_total |
čítač | status |
epochy podle stavu geometrie (1.3) |
kshana_trust_geometry_label |
gauge | label |
štítek geometrie v poslední epoše, good, fair, poor, unknown: 1 pro aktuální; nikdy se nehodnotí (skóre strhává body pouze za poor); ze vstupů, které štítek nesou (0,36) |
kshana_trust_geometry_vdop |
gauge | VDOP v poslední epoše; chybí, pokud žádný není (0.36) |
Štítek geometrie je hlavní ukazatel. Vytvářejte grafy a upozornění nad kshana_trust_geometry_label (OTLP kshana.geometry.label, CEF třetí pole cs6, LEEF geoLabel): poor je jediný štítek, za který skóre strhává body. Stav geometrie je popisný: degraded zahrnuje informativní případ sky-blocked, který může přicházet s dobrým nebo přijatelným DOP, proto nevyvolávejte poplach pouze podle kshana_trust_geometry_degraded.
Od vstupů schématu 1,3 nese kshana_trust_reason_active také štítek class (geometry, environment, inconsistency) u každého důvodu, který jej měl: třídu odečtu v poslední epoše. Řady geometrie následují po všech ostatních a jen tehdy, když vstupní epocha nese geometry (živé schéma 1,3, výsledek z enginu 0,36 nebo novějšího), takže proud nebo výsledek 0,35 se vykreslí bajt po bajtu jako dříve. Hodnoty štítků jsou pevné množiny (neznámý stav se zapíše jako unknown; neznámá třída se zahodí). Upozornění nastavte na kshana_trust_reason_active{class="inconsistency"}, nikoli pouze na pásmo, aby špatná obloha nevyvolala poplach jako útok; třída geometry je výpověď o obloze, nikoli zjištění, že k útoku nedošlo (viz docs/RECEIVER-TRUST.md).
Štítek class je součástí identity řady: když se třída důvodu mezi epochami změní (loss-of-lock z environment na geometry, pokud byly ztracené družice nízko, nebo geometry na inconsistency, pokud uvedený HDOP nesouhlasí s uvedenou oblohou), stará řada se přestane exportovat a začne nová. Pokud na třídě nezáleží, dotazujte se podle reason pomocí max by (reason) a počítejte s tím, že takový přechod vypadá jako konec jedné řady a začátek jiné. Řady schématu 1,3, štítek class a pole geometrie CEF/LEEF kontrolují vlastní testy enginu a orákula CEF (pycef, Logstash); externí orákula Prometheus a OTLP zatím proud 1,3 nemají.
Názvy důvodů se zkracují na 128 znaků a nejvýše 64 různých důvodů dostane vlastní řadu; další se počítají pod reason="other" a v kshana_trust_reason_overflow_total, takže nepřátelský nebo chybný vstup nemůže vytvořit neomezenou kardinalitu štítků.
band je jedno z calibrating, nominal, degraded, untrusted, unknown. Názvy důvodů jsou názvy monitorů proudu (kinematic, heading-course, ...; u dávkového výsledku cn0-drop, agc, raim).
Ukázkový dashboard je v deploy/grafana/kshana-gnss-trust.json (importujte jej a zvolte svůj zdroj dat Prometheus).
Syslog: CEF a LEEF#
Události se odesílají v obálce RFC 5424 (facility local0, aplikace kshana, id zprávy GNSSTRUST) přes UDP (jeden datagram na událost; IPv4 nebo IPv6) nebo TCP, ve výchozím stavu zakončené novým řádkem, nebo s --syslog-octet-counting orámované jako <length> <message> podle RFC 6587. Ve výchozím stavu se odešle jedna událost při každé změně pásma; --syslog-all odešle jednu za epochu. Dodavatel se zapisuje Ashforde OU (ASCII), aby jej žádný SIEM chybně nedekódoval.
| Pojem | Závažnost syslogu | Závažnost CEF | LEEF sev |
|---|---|---|---|
| kalibrace | 6 info | 0 | 1 |
| nominal | 6 info | 1 | 1 |
| zhoršené | 4 varování | 5 | 5 |
| nedůvěryhodné | 2 kritické | 9 | 9 |
| neznámé | 5 oznámení | 3 | 3 |
Mapování polí (id události je gnss-trust.<band>):
| Význam | CEF | LEEF 2,0 (oddělovač ^) |
|---|---|---|
| kategorie | cat=gnss-trust |
cat |
| odesílající hostitel | dvchost |
devHost |
| pásmo | cs1 (štítek band) |
band |
| důvody oddělené čárkami | cs2 (reasons) |
reasons |
| předchozí pásmo | cs3 (previousBand) |
previousBand |
| skóre | cfp1 (trustScore), vynechává se, pokud žádné není |
trustScore |
| odstup epochy, s | cfp2 (epochOffsetSeconds) |
epochOffsetSeconds |
| štítek času záznamu | cs4 (logTime) |
logTime |
| stav brány | cs5 (gate) |
gate |
stav geometrie, poté ; a třídy odečtů epochy oddělené čárkami (například degraded;environment,geometry) (vstupy 1,3); ze vstupů, které štítek nesou (0,36), třetí pole, ; a štítek, přičemž pole tříd je pak vždy přítomno (například degraded;;poor, good;;fair) |
cs6 (geometry) |
geoStatus (pouze stav), geoClass (třídy) a geoLabel (štítek) |
| HDOP (1.3) | cfp3 (geometryHdop) |
geoHdop |
| PDOP (1.3) | cfp4 (geometryPdop) |
geoPdop (0,36, se štítkem) |
| VDOP (0,36, se štítkem) | není neseno: čtyři vlastní pole s plovoucí řádovou čárkou jsou obsazena | geoVdop |
| použité družice (0,36, se štítkem) | cn1 (geometryUsedSatellites), celé číslo |
geoUsed |
| ztráta signálu: družice v dohledu nejsou sledovány, zatímco jejich geometrie je dobrá (1.3) | není neseno jako pole (žádný klíč slovníku CEF pro něj není volný): stav se zapíše jako degraded a třída odečtu geometrie jako environment v cs6 |
geoSignalLoss=1, pouze po dobu, kdy platí |
V CEF používá geometrie pouze vlastní pole ze slovníku (žádné vymyšlené klíče); štítek putuje v cs6 a ne v flexString1, protože kodek CEF v Logstash pole flexString nemapuje. Události geometrie 1,3, včetně případů se štítkem, jsou součástí řádku CEF s VALIDATED: oba parsery orákula je načtou zpět tak, jak byly zapsány (tests/cef_reference.rs, dodatky 4 a 5, každý zaregistrovaný dříve, než byl kterýkoli parser na jeho případech spuštěn). Pole štítku, VDOP a počtu družic se připojují za všechna dřívější pole a řady, a to jen u vstupů, které štítek nesou, takže vstup bez něj se vykreslí přesně jako dříve.
Prázdná pole se vynechávají (bez důvodů žádné cs2=). Název hostitele se zkracuje na 255 znaků. Hlavičkové hodnoty CEF escapují \ a |; hodnoty rozšíření escapují \, = a zalomení řádků. V hodnotách LEEF se ^ a zalomení řádků nahrazují mezerami.
OpenTelemetry (ve výchozím stavu vypnuto)#
Sestavte s --features otlp a předejte --otlp http://host:4318/v1/metrics. Exportér odesílá OTLP/HTTP JSON (kshana.trust.score, kshana.trust.band, kshana.trust.epochs, kshana.trust.reason.epochs, a pro vstupy schématu 1,3 kshana.geometry.status, kshana.geometry.degraded, kshana.geometry.signal_loss, kshana.geometry.hdop, kshana.geometry.pdop, kshana.geometry.used_satellites a ze vstupů, které štítek nesou (0,36), kshana.geometry.label (atribut label) a kshana.geometry.vdop; kumulativní součty nesou startTimeUnixNano) každých --otlp-every epoch (výchozí 10) a na konci vstupu. Nepřidává žádnou závislost a nemá TLS: posílejte na kolektor na stejném hostiteli nebo v důvěryhodném segmentu, který data předává dále přes TLS. Koncové body https:// jsou odmítnuty.