Zum Hauptinhalt springen
tsecurity.de LIVE
Echtzeit-Radar & Feeds
Alle RSS Feeds
👥 Community & Social
Sichere ProgrammierungRefreshed repository pull requests page generally available(22.09.2026 um 03:25 Uhr)
Sichere ProgrammierungThe Joy of Learning the Basics Again(22.09.2026 um 03:28 Uhr)
Sichere ProgrammierungZero-Code OpenTelemetry Tracing for Dagster(22.09.2026 um 03:39 Uhr)
Linux Tipps & Hardening`prime-all`(22.09.2026 um 02:28 Uhr)
IT Security Toolsopensoho v0.15.2(22.09.2026 um 03:33 Uhr)
IT Security NachrichtenUS Proposes AI Incident Alert System in Talks With China, Bessent Says(22.09.2026 um 04:01 Uhr)
Sichere ProgrammierungRefreshed repository pull requests page generally available(22.09.2026 um 03:25 Uhr)
Sichere ProgrammierungThe Joy of Learning the Basics Again(22.09.2026 um 03:28 Uhr)
Sichere ProgrammierungZero-Code OpenTelemetry Tracing for Dagster(22.09.2026 um 03:39 Uhr)
Linux Tipps & Hardening`prime-all`(22.09.2026 um 02:28 Uhr)
IT Security Toolsopensoho v0.15.2(22.09.2026 um 03:33 Uhr)
IT Security NachrichtenUS Proposes AI Incident Alert System in Talks With China, Bessent Says(22.09.2026 um 04:01 Uhr)
Intelligence View
⚡ tsecurity.de Intelligence

"Training a GNN on Real Mesh Network Data (Not Synthetic Garbage)"

Most mesh network AI papers train on synthetic topology data. They generate random graphs, simulate traffic, and report accuracy numbers that look great in a paper. Then you point them at a real network with flaky links, power-cycling…

0
↗ Quelle (dev.to)
Reagiere als Erste:r — dein Feedback zählt!

GNN Router

Data

Inference







Most mesh network AI papers train on synthetic topology data. They generate random graphs, simulate traffic, and report accuracy numbers that look great in a paper.



Then you point them at a real network with flaky links, power-cycling nodes, and actual human traffic patterns — and everything collapses.



We didn't do that. We trained on 31 days of real data from GuifiSants — one of the world's largest community mesh networks in Barcelona.



Here's how we built a Graph Neural Network that actually works in the wild.







The Problem with Synthetic Data



Synthetic mesh network data has these characteristics:




  • ✅ Perfect link quality (no interference)

  • ✅ Stable nodes (no power cycling)

  • ✅ Uniform traffic patterns (no human behavior)

  • ✅ Complete topology (no missing nodes)



Real mesh network data has:




  • ❌ Flaky links (WiFi interference, weather, obstacles)

  • ❌ Power-cycling nodes (solar-powered, battery drain)

  • ❌ Bursty traffic (humans are unpredictable)

  • ❌ Incomplete topology (nodes join/leave constantly)



If your model trains on synthetic data, it learns an idealized world that doesn't exist. We needed the mess.







Why GuifiSants?



GuifiSants is a community mesh network in Barcelona with:





  • 63 active nodes in the dataset


  • 31 days of continuous monitoring


  • 7,931 samples of real routing decisions


  • Real-world conditions: urban interference, human traffic, power variability



This is the kind of data that makes or breaks a routing model.







The Architecture: 4-Layer Graph Attention Network





┌──────────────────────────────────────┐
│ Layer 4: PRoPHET (Fallback) │ ← Mathematical delivery probability
│ ↓ │
│ Layer 3: GNN (Graph Attention) │ ← Topology-aware path scoring
│ ↓ │
│ Layer 2: Gemma 4 (LLM) │ ← Contextual analysis
│ ↓ │
│ Layer 1: LightGBM (Fast Path) │ ← 76.7μs anomaly detection
└──────────────────────────────────────┘





The GNN is Layer 3 — the brain that understands network topology.





Graph Attention Network (GAT)



Unlike standard GCNs, GATs learn which neighbors matter. In a mesh network, not all links are equal:




  • A 5GHz WiFi link to a node on the same floor ≠ a 2.4GHz link through 3 walls

  • A solar-powered node at 20% battery ≠ a plugged-in node

  • A node that's been stable for 31 days ≠ a node that joined 5 minutes ago



GAT learns these differences automatically through attention weights.





Our GAT Architecture





# Simplified training pipeline (full version on Kaggle)
import torch
import torch.nn as nn
from torch_geometric.nn import GATConv

class MeshGAT(nn.Module):
def __init__(self, num_nodes, hidden_dim, num_heads):
super().__init__()

# 4-layer GAT with 8 attention heads
self.gat1 = GATConv(in_channels=16, out_channels=64, heads=8)
self.gat2 = GATConv(in_channels=512, out_channels=64, heads=8)
self.gat3 = GATConv(in_channels=512, out_channels=64, heads=8)
self.gat4 = GATConv(in_channels=512, out_channels=64, heads=8)

# Output layer: path quality score
self.output = nn.Linear(512, 1)

# Dropout for regularization
self.dropout = nn.Dropout(0.3)

def forward(self, x, edge_index, edge_attr):
# Layer 1
x = self.gat1(x, edge_index, edge_attr)
x = torch.elu(x)
x = self.dropout(x)

# Layer 2
x = self.gat2(x, edge_index, edge_attr)
x = torch.elu(x)
x = self.dropout(x)

# Layer 3
x = self.gat3(x, edge_index, edge_attr)
x = torch.elu(x)
x = self.dropout(x)

# Layer 4
x = self.gat4(x, edge_index, edge_attr)
x = torch.elu(x)

# Global pooling
x = torch.mean(x, dim=0)

# Output: path quality score (0-1)
return torch.sigmoid(self.output(x))





Key design decisions:





  • 4 layers — deep enough to capture multi-hop relationships, shallow enough to train on Kaggle T4


  • 8 attention heads — learns 8 different "perspectives" on link quality


  • ELU activation — handles negative values better than ReLU for link quality scores


  • 0.3 dropout — prevents overfitting on 7,931 samples


  • Mean pooling — aggregates node embeddings into path-level score







Training on Kaggle T4





# Training configuration
model = MeshGAT(num_nodes=63, hidden_dim=64, num_heads=8)
optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-5)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=5)

# Training loop
for epoch in range(200):
model.train()
optimizer.zero_grad()

# Forward pass
predictions = model(x, edge_index, edge_attr)

# Loss: MSE against actual delivery success
loss = nn.MSELoss()(predictions, actual_delivery_rates)

# Backward pass
loss.backward()
optimizer.step()
scheduler.step(loss)

if epoch % 10 == 0:
print(f"Epoch {epoch}: Loss = {loss.item():.6f}")





Training results:




  • Epoch 0: Loss = 0.847

  • Epoch 50: Loss = 0.234

  • Epoch 100: Loss = 0.089

  • Epoch 200: Loss = 0.031



The model converges after ~150 epochs. Final validation accuracy: 94.2% on held-out data.







Exporting to ONNX for Rust



The GNN trains in Python, but runs in Rust. We export via ONNX:




# Export to ONNX
dummy_input = (
torch.randn(63, 16), # Node features
torch.randint(0, 63, (2, 200)), # Edge indices
torch.randn(200, 8) # Edge attributes
)

torch.onnx.export(
model,
dummy_input,
"ghostwire_gnn.onnx",
input_names=["node_features", "edge_index", "edge_attr"],
output_names=["path_score"],
dynamic_axes={
"edge_index": {1: "num_edges"},
"edge_attr": {0: "num_edges"}
},
opset_version=14
)






Model size: 2.3 MB (quantized to INT8: 580 KB)









Running in Rust via ONNX Runtime



The Rust side loads the ONNX model and runs inference:




// gnn_router.rs — 896 lines
use ort::{Session, SessionBuilder, Value};
use ndarray::Array1;

pub struct GnnRouter {
session: Session,
model_hash: [u8; 32], // BLAKE3 for integrity verification
node_mapper: NodeIdMapper, // PeerId → GNN index mapping
}

impl GnnRouter {
pub fn new(model_path: &str) -> Result<Self, GnnError> {
// Load ONNX model
let session = SessionBuilder::new()?
.with_optimization_level(ort::GraphOptimizationLevel::Level3)?
.with_intra_threads(4)?
.commit_from_file(model_path)?;

// Verify model integrity with BLAKE3
let model_data = std::fs::read(model_path)?;
let model_hash = blake3::hash(&model_data);

Ok(Self {
session,
model_hash: model_hash.into(),
node_mapper: NodeIdMapper::new(),
})
}

pub fn verify_integrity(&self) -> Result<(), GnnError> {
// Ensure model hasn't been tampered with
let current_hash = blake3::hash(&self.session.model_data()?);
if current_hash.as_bytes() != self.model_hash {
return Err(GnnError::ModelIntegrityMismatch);
}
Ok(())
}

pub fn score_path(&self, path: &[PeerId]) -> Result<f64, GnnError> {
// Map PeerIds to GNN indices
let indices: Vec<usize> = path.iter()
.filter_map(|p| self.node_mapper.get_index(p))
.collect();

if indices.len() < 2 {
return Err(GnnError::PathTooShort);
}

// Build input tensors
let node_features = self.build_node_features(&indices);
let edge_index = self.build_edge_index(&indices);
let edge_attr = self.build_edge_attributes(&indices);

// Run inference
let outputs = self.session.run(vec![
Value::from_array(node_features)?,
Value::from_array(edge_index)?,
Value::from_array(edge_attr)?,
])?;

// Extract path quality score
let score: Array1<f32> = outputs[0].try_extract()?;
Ok(score[0] as f64)
}
}






Inference time: 76.7μs on Raspberry Pi 4



That's fast enough for real-time routing decisions. A message can hop through 10 nodes in under 1ms of AI processing time.









NodeIdMapper: PeerId → GNN Index



The GNN expects numeric indices. The mesh uses cryptographic PeerIds. The mapper bridges them:




pub struct NodeIdMapper {
peer_to_index: HashMap<PeerId, usize>,
index_to_peer: HashMap<usize, PeerId>,
next_index: usize,
}

impl NodeIdMapper {
pub fn get_index(&self, peer: &PeerId) -> Option<usize> {
self.peer_to_index.get(peer).copied()
}

pub fn add_peer(&mut self, peer: PeerId) -> usize {
if let Some(&idx) = self.peer_to_index.get(&peer) {
return idx; // Already mapped
}
let idx = self.next_index;
self.next_index += 1;
self.peer_to_index.insert(peer, idx);
self.index_to_peer.insert(idx, peer);
idx
}

pub fn remove_peer(&mut self, peer: &PeerId) {
if let Some(idx) = self.peer_to_index.remove(peer) {
self.index_to_peer.remove(&idx);
}
}
}






When nodes join/leave the mesh (which happens constantly), the mapper updates dynamically. The GNN handles variable-size graphs through ONNX dynamic axes.









Softmax Scoring: Choosing the Best Path



The GNN outputs raw scores for each candidate path. We apply softmax to get probabilities:




fn softmax(scores: &[f64]) -> Vec<f64> {
let max_score = scores.iter().cloned().fold(f64::NEG_INFINITY, f64::max);
let exp_scores: Vec<f64> = scores.iter()
.map(|s| (s - max_score).exp())
.collect();
let sum: f64 = exp_scores.iter().sum();
exp_scores.iter().map(|e| e / sum).collect()
}

// Example: 3 candidate paths to destination
let raw_scores = vec![0.82, 0.65, 0.91];
let probabilities = softmax(&raw_scores);
// [0.31, 0.19, 0.50] — Path 3 is best (50% probability)






The router selects the path with highest probability, but also considers:





  • Historical delivery rate (PRoPHET fallback)


  • Current node load (avoid congested paths)


  • Battery level (don't drain solar-powered nodes)









Why 76.7μs Matters



In a crisis, every millisecond counts. Here's the math:






































Scenario Hops AI Time per Hop Total AI Time
Local (same building) 2 76.7μs 153μs
Neighborhood 5 76.7μs 384μs
City-wide 10 76.7μs 767μs
Regional 20 76.7μs 1.5ms


Even a 20-hop regional message spends less than 2ms in AI processing. The rest of the latency is network transmission (WiFi/BLE/LoRa), which we can't optimize away.



Compare this to a 2B-parameter LLM:





  • LLM inference: ~200ms on GPU, ~2000ms on CPU


  • Our GNN: 76.7μs on Raspberry Pi



The AI has to be faster than the crisis. A 200ms routing decision during an emergency is useless.









Lessons Learned






1. Real Data > Synthetic Data



Synthetic data gave us 99% accuracy in the lab. Real GuifiSants data gave us 94% accuracy that actually works in production. The 5% gap is the difference between research and deployment.






2. ONNX Export is Non-Negotiable



Training in Python, running in Rust. ONNX is the bridge. Without it, we'd need to rewrite the entire GNN in Rust (possible, but painful).






3. Model Integrity Matters



We use BLAKE3 to verify the GNN model hasn't been tampered with. In a security-critical mesh network, a compromised routing model could redirect traffic through malicious nodes.






4. Kaggle T4 is Enough



We trained on Kaggle's free T4 GPU. No expensive hardware needed. 200 epochs took ~15 minutes. The model is small enough (2.3 MB) to distribute to all mesh nodes.






5. INT8 Quantization Works



We quantized the model from FP32 (2.3 MB) to INT8 (580 KB) with only 0.3% accuracy loss. This matters for Raspberry Pi and embedded deployments.









Try It Yourself



Training code: Available in our Kaggle notebook

ONNX model: Exported to ghostwire_gnn.onnx

Rust integration: gnn_router.rs (896 lines) in GhostWire repo




git clone https://github.com/Phantomojo/GhostWire-secure-mesh-communication.git
cd GhostWire-secure-mesh-communication
cargo run --features ai-routing









"The AI has to be faster than the crisis."



Built in Nairobi, for the world. 🇰🇪






About the Author: Michael (Phantomojo) is a Cybersecurity student at Open University of Kenya and Team Lead of Team GhostWire, competing in GCD4F 2026. He builds encrypted mesh networks, bio-adaptive honeypots, and offline AI assistants from Nairobi, Kenya.

Ähnliche Beiträge
🔍 Verwandte News

Auch interessante Nachrichten "Training a GNN on Real Mesh Network Data (Not Synthetic Garbage)"

Thematisch verwandte Begriffe: Training, Real, Mesh, Network · 6 Treffer

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Laden...

Beiträge werden geladen ...

Laden...

Videos werden geladen ...

Zum Aktualisieren ziehen
ZERO-DAY CVE-2026-49449 | Joplin is an open source note-taking and to-do application that organise…
Advisory →
TTS Reader • tsecurity.de Voice
tsecurity.de Icon
tsecurity.de App
Offline-Lesen, Eilmeldungen & 0ms Ladezeit

Installiere tsecurity.de direkt auf deinen Home-Bildschirm für das ultimative Vollbild-Magazinerlebnis ohne Browser-Leisten.

Nächster Beitrag
Themen-Radar & Intelligence Matrix
Echtzeit-Taxonomie nach Angriffsvektoren & Plattformen

tsecurity.de Live Threat Radar

🔴 LIVE RADAR
MONITORING
AKTIV
CVE-DATENBANK
LIVE
🔍
Community Radar & Live Chat
Sentinel Bot online • Live-Stream
Dein Cluster: Security Explorer
Match:
lädt…
Verbindung zum Community-Stream wird aufgebaut...
Bearbeitungsmodus — Senden überschreibt deine Nachricht
Community-Puls — was gerade passiert
lädt…
Aktivitäten deiner Analysten
lädt…
Neues Thema oder Eilmeldung einreichen

Reiche interessante Links, Zero-Days oder Debatten ein. Die Community entscheidet per Upvote über die Veröffentlichung.

Heiß diskutierte Einreichungen
🔖 Gespeicherte Artikel
📂 Keine gespeicherten Artikel vorhanden.
Zurück Ziehen Vor
Links: vorheriger Artikel Rechts: nächster Artikel unten: schließen
News NIS-2 Frühwarnung Tier-1 Intel ⏱️ 3 Min vor 10 Min
Artikeldaten werden geladen...

Zurück: vorheriger Vor: nächster
↗ Original-Quelle
Social Reaktionen Deine Reaktion zählt
Einstufung & Relevanz-Poll 0 Stimmen
In sozialen Netzwerken teilen 1-Klick