docs/networking/dns.mdx
DNS queries from the sandbox are intercepted on the host. Rather than letting the guest talk to a resolver directly, microsandbox proxies each query, which lets you:
The knobs below cover the day-to-day controls. For the rebinding and TOCTOU protections that also ride on the interceptor, see the security model.
Domain blocking lives in the network policy as deny Domain(...) / deny DomainSuffix(...) rules. The interceptor enforces them at three layers:
REFUSED response; the upstream resolver never sees them.The bulk-deny shortcuts in each SDK are convenience for deny Domain / deny DomainSuffix rules; they prepend onto whatever policy is set so the deny takes precedence over later allow rules.
let sb = Sandbox::builder("safe-agent") .image("python") .network(|n| n.policy(policy)) .create() .await?;
```typescript TypeScript
import { Sandbox } from "microsandbox";
await using sb = await Sandbox.builder("safe-agent")
.image("python")
.network({
denyDomains: ["malware.example.com"],
denyDomainSuffixes: [".tracking.com"],
})
.create();
from microsandbox import Network, Sandbox
sb = await Sandbox.create(
"safe-agent",
image="python",
network=Network(
deny_domains=("malware.example.com",),
deny_domain_suffixes=(".tracking.com",),
),
)
msb create python --name safe-agent \
--deny-domain malware.example.com \
--deny-domain-suffix .tracking.com
By default the sandbox picks up the host's resolver list automatically:
State:/Network/Global/DNS from the system configuration store, with /etc/resolv.conf as a fallback when the store isn't available./etc/resolv.conf directly.You can override this by setting nameservers to pin the exact resolvers you want (e.g. 1.1.1.1, dns.google), which is useful when auto-discovery picks the wrong ones.
Values can be plain IPs, IP:PORT, hostnames, or HOST:PORT. Hostnames are resolved once at sandbox startup using the host's OS resolver.
let sb = Sandbox::builder("safe-agent") .image("python") .network(|n| n .dns(|d| d .nameservers([ "1.1.1.1".parse::<Nameserver>()?, "1.0.0.1".parse::<Nameserver>()?, ]) .query_timeout_ms(3000) ) ) .create() .await?;
```typescript TypeScript
await using sb = await Sandbox.builder("safe-agent")
.image("python")
.network((n) => n.dns((d) =>
d.nameservers(["1.1.1.1", "1.0.0.1"])
.queryTimeoutMs(3000),
))
.create();
sb = await Sandbox.create(
"safe-agent",
image="python",
network=Network(
dns=DnsConfig(
nameservers=("1.1.1.1", "1.0.0.1"),
query_timeout_ms=3000,
),
),
)
msb create python --name safe-agent \
--dns-nameserver 1.1.1.1 \
--dns-nameserver 1.0.0.1 \
--dns-query-timeout-ms 3000
If the guest aims a query at a specific resolver (dig @1.1.1.1, an /etc/resolv.conf entry inside the guest, or a library call that takes a resolver IP), the interceptor forwards the query to that resolver directly instead of redirecting it to the pinned defaults. The network policy still applies: the query only goes through if the destination IP is allowed.
The block list and rebind protection only apply to queries the gateway can see. A guest that routes DNS through an encrypted or non-DNS protocol bypasses both unless the gateway intercepts or refuses it.
Intercepted (block list and rebind protection apply):
Refused (guest's stub falls back to plain DNS):
Not distinguishable from regular traffic (operator must filter via network policy):
For strict DNS integrity, combine DoT interception with a network policy denying egress UDP/53, TCP/53, and TCP/853 to anything except the gateway.
Network policy rules can match a destination by exact domain or by suffix. The interceptor watches DNS responses as they flow back to the guest and keeps track of which IP addresses belong to which domain.
A connection to 93.184.216.34 is only allowed by a rule targeting example.com if that IP actually came back as an answer to a lookup for example.com from this sandbox.
Because of that, domain rules only take effect on connections that are preceded by a DNS lookup from inside the sandbox. An application that connects to a hard-coded IP it didn't resolve through the interceptor won't match any domain rule.