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 /// Whether DNS rebinding protection is enabled.
96 #[serde(default = "default_true")]
97 pub rebind_protection: bool,
98
99 /// Nameservers to forward DNS queries to. When empty, fall back to
100 /// the `nameserver` entries in the host's `/etc/resolv.conf`. Set
101 /// this to pin specific resolvers (e.g. `1.1.1.1:53`, `dns.google`)
102 /// or to work around split-DNS / VPN setups where the host's
103 /// resolv.conf is incomplete. Accepts IPs, `IP:PORT`, or hostnames
104 /// (resolved once at startup via the host's OS resolver).
105 #[serde(default)]
106 pub nameservers: Vec<Nameserver>,
107
108 /// Per-query timeout in milliseconds. Default: 5000.
109 #[serde(default = "default_query_timeout_ms")]
110 pub query_timeout_ms: u64,
111}
112
113/// A published port mapping between host and guest.
114#[derive(Debug, Clone, Serialize, Deserialize)]
115pub struct PublishedPort {
116 /// Host-side port to bind.
117 pub host_port: u16,
118
119 /// Guest-side port to forward to.
120 pub guest_port: u16,
121
122 /// Protocol (TCP or UDP).
123 #[serde(default)]
124 pub protocol: PortProtocol,
125
126 /// Host address to bind. Defaults to loopback.
127 #[serde(default = "default_host_bind")]
128 pub host_bind: IpAddr,
129}
130
131/// Protocol for a published port.
132#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
133pub enum PortProtocol {
134 /// TCP (default).
135 #[default]
136 Tcp,
137
138 /// UDP.
139 Udp,
140}
141
142//--------------------------------------------------------------------------------------------------
143// Trait Implementations
144//--------------------------------------------------------------------------------------------------
145
146impl Default for NetworkConfig {
147 fn default() -> Self {
148 Self {
149 enabled: true,
150 interface: InterfaceOverrides::default(),
151 ports: Vec::new(),
152 policy: NetworkPolicy::default(),
153 dns: DnsConfig::default(),
154 tls: TlsConfig::default(),
155 secrets: SecretsConfig::default(),
156 max_connections: None,
157 trust_host_cas: false,
158 }
159 }
160}
161
162impl Default for DnsConfig {
163 fn default() -> Self {
164 Self {
165 rebind_protection: true,
166 nameservers: Vec::new(),
167 query_timeout_ms: default_query_timeout_ms(),
168 }
169 }
170}
171
172//--------------------------------------------------------------------------------------------------
173// Functions
174//--------------------------------------------------------------------------------------------------
175
176fn default_true() -> bool {
177 true
178}
179
180fn default_host_bind() -> IpAddr {
181 IpAddr::V4(Ipv4Addr::LOCALHOST)
182}
183
184fn default_query_timeout_ms() -> u64 {
185 5000
186}