Skip to main content

microsandbox_network/
config.rs

1//! Serializable network configuration types.
2//!
3//! These types represent the user-facing declarative network configuration
4//! for sandbox networking. Designed for the smoltcp in-process engine.
5
6use std::net::{IpAddr, Ipv4Addr, Ipv6Addr};
7
8use serde::{Deserialize, Serialize};
9
10use crate::dns::Nameserver;
11
12use crate::policy::NetworkPolicy;
13use crate::secrets::config::SecretsConfig;
14use crate::tls::TlsConfig;
15
16//--------------------------------------------------------------------------------------------------
17// Types
18//--------------------------------------------------------------------------------------------------
19
20/// Complete network configuration for a sandbox.
21///
22/// Narrowed for the smoltcp in-process engine. Gateway, prefix length, and
23/// other host-backend details are engine internals derived from the sandbox
24/// slot — the user only specifies what matters: interface overrides, ports,
25/// policy, DNS, TLS, and connection limits.
26#[derive(Debug, Clone, Serialize, Deserialize)]
27pub struct NetworkConfig {
28    /// Whether networking is enabled for this sandbox.
29    #[serde(default = "default_true")]
30    pub enabled: bool,
31
32    /// Guest interface overrides. Unset fields derived from sandbox slot.
33    #[serde(default)]
34    pub interface: InterfaceOverrides,
35
36    /// Host → guest port mappings.
37    #[serde(default)]
38    pub ports: Vec<PublishedPort>,
39
40    /// Egress/ingress policy rules.
41    #[serde(default)]
42    pub policy: NetworkPolicy,
43
44    /// DNS interception and filtering settings.
45    #[serde(default)]
46    pub dns: DnsConfig,
47
48    /// TLS interception settings.
49    #[serde(default)]
50    pub tls: TlsConfig,
51
52    /// Secret injection settings.
53    #[serde(default)]
54    pub secrets: SecretsConfig,
55
56    /// Max concurrent guest connections. Default: 256.
57    #[serde(default)]
58    pub max_connections: Option<usize>,
59
60    /// Ship the host's trusted root CAs into the guest at boot so outbound
61    /// TLS works behind corporate MITM proxies (Cloudflare Warp Zero
62    /// Trust, Zscaler, Netskope, etc.) whose gateway CA is installed on
63    /// the host but not shipped in the Mozilla root bundle the guest OS
64    /// uses. Opt-in: host trust is not copied into the guest unless
65    /// this is explicitly enabled. Default: false.
66    #[serde(default)]
67    pub trust_host_cas: bool,
68}
69
70/// Optional overrides for the guest interface.
71///
72/// If omitted, values are derived deterministically from the sandbox slot.
73#[derive(Debug, Clone, Default, Serialize, Deserialize)]
74pub struct InterfaceOverrides {
75    /// Guest MAC address. Default: derived from slot.
76    #[serde(default)]
77    pub mac: Option<[u8; 6]>,
78
79    /// Interface MTU. Default: 1500.
80    #[serde(default)]
81    pub mtu: Option<u16>,
82
83    /// Guest IPv4 address. Default: derived from slot (100.96.0.0/11 pool).
84    #[serde(default)]
85    pub ipv4_address: Option<Ipv4Addr>,
86
87    /// Guest IPv6 address. Default: derived from slot (fd42:6d73:62::/48 pool).
88    #[serde(default)]
89    pub ipv6_address: Option<Ipv6Addr>,
90}
91
92/// DNS interception settings for the sandbox.
93#[derive(Debug, Clone, Serialize, Deserialize)]
94pub struct DnsConfig {
95    /// Exact domains to refuse locally.
96    #[serde(default)]
97    pub blocked_domains: Vec<String>,
98
99    /// Domain suffixes to refuse locally.
100    #[serde(default)]
101    pub blocked_suffixes: Vec<String>,
102
103    /// Whether DNS rebinding protection is enabled.
104    #[serde(default = "default_true")]
105    pub rebind_protection: bool,
106
107    /// Nameservers to forward DNS queries to. When empty, fall back to
108    /// the `nameserver` entries in the host's `/etc/resolv.conf`. Set
109    /// this to pin specific resolvers (e.g. `1.1.1.1:53`, `dns.google`)
110    /// or to work around split-DNS / VPN setups where the host's
111    /// resolv.conf is incomplete. Accepts IPs, `IP:PORT`, or hostnames
112    /// (resolved once at startup via the host's OS resolver).
113    #[serde(default)]
114    pub nameservers: Vec<Nameserver>,
115
116    /// Per-query timeout in milliseconds. Default: 5000.
117    #[serde(default = "default_query_timeout_ms")]
118    pub query_timeout_ms: u64,
119}
120
121/// A published port mapping between host and guest.
122#[derive(Debug, Clone, Serialize, Deserialize)]
123pub struct PublishedPort {
124    /// Host-side port to bind.
125    pub host_port: u16,
126
127    /// Guest-side port to forward to.
128    pub guest_port: u16,
129
130    /// Protocol (TCP or UDP).
131    #[serde(default)]
132    pub protocol: PortProtocol,
133
134    /// Host address to bind. Defaults to loopback.
135    #[serde(default = "default_host_bind")]
136    pub host_bind: IpAddr,
137}
138
139/// Protocol for a published port.
140#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
141pub enum PortProtocol {
142    /// TCP (default).
143    #[default]
144    Tcp,
145
146    /// UDP.
147    Udp,
148}
149
150//--------------------------------------------------------------------------------------------------
151// Trait Implementations
152//--------------------------------------------------------------------------------------------------
153
154impl Default for NetworkConfig {
155    fn default() -> Self {
156        Self {
157            enabled: true,
158            interface: InterfaceOverrides::default(),
159            ports: Vec::new(),
160            policy: NetworkPolicy::default(),
161            dns: DnsConfig::default(),
162            tls: TlsConfig::default(),
163            secrets: SecretsConfig::default(),
164            max_connections: None,
165            trust_host_cas: false,
166        }
167    }
168}
169
170impl Default for DnsConfig {
171    fn default() -> Self {
172        Self {
173            blocked_domains: Vec::new(),
174            blocked_suffixes: Vec::new(),
175            rebind_protection: true,
176            nameservers: Vec::new(),
177            query_timeout_ms: default_query_timeout_ms(),
178        }
179    }
180}
181
182//--------------------------------------------------------------------------------------------------
183// Functions
184//--------------------------------------------------------------------------------------------------
185
186fn default_true() -> bool {
187    true
188}
189
190fn default_host_bind() -> IpAddr {
191    IpAddr::V4(Ipv4Addr::LOCALHOST)
192}
193
194fn default_query_timeout_ms() -> u64 {
195    5000
196}