Skip to main content

heldar_kernel/services/
remote_access.rs

1//! Remote-access overlay awareness (open kernel platform feature; see `docs/REMOTE-ACCESS.md`).
2//!
3//! A Heldar deployment is typically behind CGNAT (no inbound port-forward, DDNS useless). The
4//! supported way to reach it remotely is a **WireGuard overlay** — Tailscale for personal/dev use,
5//! NetBird self-hosted for shipped products — running as an EXTERNAL daemon on the host. The overlay
6//! is deliberately *orthogonal* to the media stack: MediaMTX and this API keep serving on their
7//! normal ports, now reachable over the overlay's interface by authorized peers. Connections are
8//! P2P-first (direct hole-punched / IPv6 when possible) and end-to-end encrypted, so no relay can
9//! ever read camera video.
10//!
11//! The kernel does **not** embed or manage WireGuard — that would duplicate mature daemons. It only
12//! *observes* the configured overlay interface and reports whether remote access is currently
13//! functional, so the dashboard/health surface can show it without log-diving. This keeps the
14//! capability fully open (Apache-2.0) and transport-agnostic.
15
16use serde::Serialize;
17
18use crate::config::Config;
19
20/// Health of the remote-access overlay, surfaced via `/api/v1/system`.
21#[derive(Debug, Clone, Serialize)]
22pub struct OverlayStatus {
23    /// Whether remote access via an overlay is configured at all (else the deployment is LAN-only).
24    pub enabled: bool,
25    /// `tailscale` | `netbird` | `wireguard` | `none`.
26    pub kind: String,
27    /// The probed interface (e.g. `tailscale0`), if configured.
28    pub iface: Option<String>,
29    /// Whether that interface currently exists on the host (i.e. the overlay daemon created it).
30    pub present: bool,
31    /// Raw `operstate` of the interface, if readable.
32    pub operstate: Option<String>,
33    /// Whether remote access is considered functional right now.
34    pub up: bool,
35    /// Human-readable explanation for the dashboard.
36    pub note: String,
37}
38
39/// A TUN/overlay interface is "up" when it exists and its operstate is `up` or `unknown`. WireGuard
40/// and Tailscale TUN devices commonly report `unknown` even when fully functional (the kernel does
41/// not track carrier on a point-to-point TUN), so `unknown` must NOT be treated as down.
42fn is_up(present: bool, operstate: Option<&str>) -> bool {
43    present && matches!(operstate, None | Some("up") | Some("unknown"))
44}
45
46/// Probe the configured overlay interface and report remote-access health. Dependency-free: reads
47/// `/sys/class/net/<iface>` (Linux), so it is cheap enough to call per `/system` request.
48pub fn status(cfg: &Config) -> OverlayStatus {
49    if !cfg.overlay_enabled {
50        return OverlayStatus {
51            enabled: false,
52            kind: cfg.overlay_kind.clone(),
53            iface: cfg.overlay_iface.clone(),
54            present: false,
55            operstate: None,
56            up: false,
57            note: "Remote-access overlay disabled (HELDAR_OVERLAY_ENABLED=false); reachable on the LAN only."
58                .into(),
59        };
60    }
61    let Some(iface) = cfg.overlay_iface.clone() else {
62        return OverlayStatus {
63            enabled: true,
64            kind: cfg.overlay_kind.clone(),
65            iface: None,
66            present: false,
67            operstate: None,
68            up: false,
69            note: "Overlay enabled but HELDAR_OVERLAY_IFACE is unset; cannot determine status."
70                .into(),
71        };
72    };
73
74    let base = std::path::Path::new("/sys/class/net").join(&iface);
75    let present = base.exists();
76    let operstate = std::fs::read_to_string(base.join("operstate"))
77        .ok()
78        .map(|s| s.trim().to_string());
79    let up = is_up(present, operstate.as_deref());
80
81    let note = if !present {
82        format!(
83            "Overlay interface '{iface}' not found — is the {} daemon running and connected?",
84            cfg.overlay_kind
85        )
86    } else if up {
87        format!(
88            "Overlay '{}' up on '{iface}'; deployment reachable to authorized peers (P2P-first, end-to-end encrypted).",
89            cfg.overlay_kind
90        )
91    } else {
92        format!(
93            "Overlay interface '{iface}' present but not up (operstate={}).",
94            operstate.as_deref().unwrap_or("?")
95        )
96    };
97
98    OverlayStatus {
99        enabled: true,
100        kind: cfg.overlay_kind.clone(),
101        iface: Some(iface),
102        present,
103        operstate,
104        up,
105        note,
106    }
107}
108
109#[cfg(test)]
110mod tests {
111    use super::*;
112
113    #[test]
114    fn tun_unknown_counts_as_up() {
115        // TUN devices report "unknown" when functional — must be treated as up.
116        assert!(is_up(true, Some("unknown")));
117        assert!(is_up(true, Some("up")));
118        assert!(is_up(true, None));
119    }
120
121    #[test]
122    fn down_or_absent_is_not_up() {
123        assert!(!is_up(true, Some("down")));
124        assert!(!is_up(false, Some("up")));
125        assert!(!is_up(false, None));
126    }
127}