> ## Documentation Index
> Fetch the complete documentation index at: https://microsanbox-staging-toks-cloud-snapshot-contracts.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# DNS

> Control how sandboxes resolve domain names

microsandbox handles DNS queries on the host instead of letting the guest contact a resolver directly. This makes domain rules and DNS rebinding protection possible.

## DNS as egress

Every DNS query must pass the sandbox's egress policy.

| Rule                    | How it applies to DNS                                                        |
| ----------------------- | ---------------------------------------------------------------------------- |
| Domain or domain suffix | Matches the requested name directly. Protocol and port filters do not apply. |
| `Any`                   | Matches the protocol and port used for the query                             |
| `Group::Host`           | Matches the gateway that handles the query                                   |
| IP or CIDR              | Does not match because the name has not been resolved yet                    |

The `public`, `private`, and `host` profiles already allow DNS through the gateway. With a custom deny-by-default policy, add the equivalent of `allow_dns()` or use `allow@dns` in the CLI. Otherwise, every lookup will be denied.

DNS over TLS uses TCP port `853` and needs its own allow rule. It also requires [TLS MITM](/networking/tls).

DNS rebinding protection is separate from query access. microsandbox rejects private or reserved answers unless an explicit address rule allows them. An allow-by-default policy does not disable this protection. See [Network defenses](/security/network) for the full policy behavior.

## Blocking domains

microsandbox returns a local `NXDOMAIN` response for denied domains and never forwards them to the upstream resolver. The same rules also protect connections that use TLS SNI or a recently resolved IP address.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Sandbox } from "microsandbox";

  await using sb = await Sandbox.builder("safe-agent")
    .image("python")
    .network({
      denyDomains: ["malware.example.com"],
      denyDomainSuffixes: [".tracking.com"],
    })
    .create();
  ```

  ```rust Rust theme={null}
  let policy = NetworkPolicy::builder()
      .default_allow()
      .egress(|e| e
          .deny_domains(["malware.example.com"])
          .deny_domain_suffixes([".tracking.com"]))
      .build()?;

  let sb = Sandbox::builder("safe-agent")
      .image("python")
      .network(|n| n.policy(policy))
      .create()
      .await?;
  ```

  ```python Python theme={null}
  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",),
      ),
  )
  ```

  ```go Go theme={null}
  sb, err := m.CreateSandbox(ctx, "safe-agent",
      m.WithImage("python"),
      m.WithNetwork(&m.NetworkConfig{
          DenyDomains:        []string{"malware.example.com"},
          DenyDomainSuffixes: []string{".tracking.com"},
      }),
  )
  ```

  ```bash CLI theme={null}
  msb create python --name safe-agent --net-default allow \
    --net-rule "deny@malware.example.com,deny@*.tracking.com"
  ```
</CodeGroup>

## Pinning nameservers

<Tooltip tip="Custom nameservers are not available on microsandbox cloud. Cloud sandboxes use platform-managed DNS."><span className="msb-badge-local">Local-only <Icon icon="circle-info" size={11} /></span></Tooltip>

By default, microsandbox uses the host's resolver list. Set `nameservers` when you need specific resolvers.

Nameservers can be IP addresses, hostnames, or either form with a port. microsandbox resolves hostnames once when the sandbox starts.

microsandbox tries resolvers in order. A timeout or connection failure moves to the next resolver. DNS responses such as `SERVFAIL` and `REFUSED` do not. Each unreachable resolver can delay the query by up to `query_timeout_ms`.

<CodeGroup>
  ```typescript TypeScript theme={null}
  import { Sandbox } from "microsandbox";

  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();
  ```

  ```rust Rust theme={null}
  use microsandbox_network::dns::Nameserver;

  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?;
  ```

  ```python Python theme={null}
  from microsandbox import Network, Sandbox
  from microsandbox.types import DnsConfig

  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,
          ),
      ),
  )
  ```

  ```go Go theme={null}
  timeout := uint64(3000)
  sb, err := m.CreateSandbox(ctx, "safe-agent",
      m.WithImage("python"),
      m.WithNetwork(&m.NetworkConfig{
          DNS: &m.DNSConfig{
              Nameservers:    []string{"1.1.1.1", "1.0.0.1"},
              QueryTimeoutMs: &timeout,
          },
      }),
  )
  ```

  ```bash CLI theme={null}
  msb create python --name safe-agent \
    --dns-nameserver 1.1.1.1 \
    --dns-nameserver 1.0.0.1 \
    --dns-query-timeout-ms 3000
  ```
</CodeGroup>

An application can request a specific resolver, such as with `dig @1.1.1.1`. That request skips the configured default list, but it still has to pass the network policy.

## DNS over alternative transports

| Transport                                  | Behavior                                          |
| ------------------------------------------ | ------------------------------------------------- |
| UDP or TCP on port `53`                    | Intercepted                                       |
| DNS over TLS on TCP port `853`             | Intercepted when TLS MITM is enabled              |
| DNS over QUIC, mDNS, LLMNR, and NetBIOS-NS | Refused so the guest can fall back to regular DNS |
| DNS over HTTPS                             | Treated as normal HTTPS traffic                   |

Domain blocking and rebinding protection apply only to DNS traffic that microsandbox can identify. Use network rules to control DNS over HTTPS or to restrict which resolvers the guest can reach.

## Domain-based policy rules

microsandbox records the IP addresses returned for each domain. A domain rule matches a later connection only when that sandbox resolved the domain to that IP.

An application that connects directly to a hard-coded IP does not match a domain rule. Use an IP or CIDR rule for that traffic.

## Reference

For exact DNS and network APIs, see [TypeScript](/sdk/typescript/networking#dnsbuilder), [Rust](/sdk/rust/networking#dnsbuilder), [Python](/sdk/python/networking#dnsconfig), or [Go](/sdk/go/networking#dnsconfig). For CLI fields and flags, see [Configuration file](/cli/configuration#network) and [Sandbox commands](/cli/sandbox-commands).

## Related

* [Network defenses](/security/network) explains rebinding protection and DNS-to-IP binding.
* [TLS MITM](/networking/tls) explains inspection for HTTPS and DNS over TLS.
