chore(connlib): include "packet kind" in decapsulation errors (#10867)

When looking at error logs from Gateways or Clients, it can be useful to
know, what kind of packet we failed to process.
This commit is contained in:
Thomas Eizinger
2025-11-12 15:26:20 +11:00
committed by GitHub
parent ee38ccc120
commit 8af8978ad5
4 changed files with 58 additions and 13 deletions

View File

@@ -10,7 +10,7 @@ use crate::gateway::flow_tracker::FlowTracker;
use crate::messages::gateway::{Client, ResourceDescription, Subject};
use crate::messages::{Answer, IceCredentials, ResolveRequest};
use crate::peer_store::PeerStore;
use crate::{GatewayEvent, IpConfig, p2p_control};
use crate::{FailedToDecapsulate, GatewayEvent, IpConfig, p2p_control, packet_kind};
use anyhow::{Context, Result};
use boringtun::x25519::{self, PublicKey};
use chrono::{DateTime, Utc};
@@ -164,7 +164,7 @@ impl GatewayState {
let Some((cid, packet)) = self
.node
.decapsulate(local, from, packet, now)
.context("Failed to decapsulate")?
.context(FailedToDecapsulate(packet_kind::classify(packet)))?
else {
return Ok(None);
};

View File

@@ -34,6 +34,7 @@ mod io;
pub mod messages;
mod otel;
mod p2p_control;
mod packet_kind;
mod peer_store;
#[cfg(all(test, feature = "proptest"))]
mod proptest;
@@ -647,6 +648,10 @@ pub(crate) struct NotClientIp(IpAddr);
#[error("Traffic to/from this resource IP is not allowed: {0}")]
pub(crate) struct NotAllowedResource(IpAddr);
#[derive(Debug, thiserror::Error)]
#[error("Failed to decapsulate '{0}' packet")]
pub(crate) struct FailedToDecapsulate(packet_kind::Kind);
pub fn is_peer(dst: IpAddr) -> bool {
match dst {
IpAddr::V4(v4) => IPV4_TUNNEL.contains(v4),

View File

@@ -6,17 +6,7 @@ pub mod attr {
pub fn network_protocol_name(payload: &[u8]) -> KeyValue {
const KEY: &str = "network.protocol.name";
match payload {
[0..3, ..] => KeyValue::new(KEY, "stun"),
// Channel-data is a 4-byte header so the actual payload starts on the 5th byte
[64..=79, _, _, _, 0..3, ..] => KeyValue::new(KEY, "stun-over-turn"),
[64..=79, _, _, _, payload @ ..] if snownet::is_wireguard(payload) => {
KeyValue::new(KEY, "wireguard-over-turn")
}
[64..=79, _, _, _, ..] => KeyValue::new(KEY, "unknown-over-turn"),
payload if snownet::is_wireguard(payload) => KeyValue::new(KEY, "wireguard"),
_ => KeyValue::new(KEY, "unknown"),
}
KeyValue::new(KEY, crate::packet_kind::classify(payload))
}
}

View File

@@ -0,0 +1,50 @@
use std::fmt;
#[derive(Debug)]
pub enum Kind {
Stun,
Wireguard,
Unknown,
StunOverTurn,
WireguardOverTurn,
UnknownOverTurn,
}
impl fmt::Display for Kind {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{}", self.as_str())
}
}
impl Kind {
pub fn as_str(&self) -> &'static str {
match self {
Kind::Stun => "stun",
Kind::Wireguard => "wireguard",
Kind::Unknown => "unknown",
Kind::StunOverTurn => "stun-over-turn",
Kind::WireguardOverTurn => "wireguard-over-turn",
Kind::UnknownOverTurn => "unknown-over-turn",
}
}
}
impl From<Kind> for opentelemetry::Value {
fn from(val: Kind) -> Self {
opentelemetry::Value::String(opentelemetry::StringValue::from(val.as_str()))
}
}
pub fn classify(packet: &[u8]) -> Kind {
match packet {
[0..=3, ..] => Kind::Stun,
// Channel-data is a 4-byte header so the actual payload starts on the 5th byte
[64..=79, _, _, _, 0..=3, ..] => Kind::StunOverTurn,
[64..=79, _, _, _, payload @ ..] if snownet::is_wireguard(payload) => {
Kind::WireguardOverTurn
}
[64..=79, _, _, _, ..] => Kind::UnknownOverTurn,
payload if snownet::is_wireguard(payload) => Kind::Wireguard,
_ => Kind::Unknown,
}
}