Skip to main content

Overview

The OpenSandbox Egress Sidecar provides FQDN-based egress control for sandbox environments. It runs alongside the sandbox application container (sharing the same network namespace) and enforces declared network policies to control outbound traffic.
Status: Implementing. Currently supports Layer 1 (DNS Proxy). Layer 2 (Network Filter) is on the roadmap.See OSEP-0001: FQDN-based Egress Control for the detailed design.

Features

  • FQDN-based Allowlist: Control outbound traffic by domain name (e.g., api.github.com)
  • Wildcard Support: Allow subdomains using wildcards (e.g., *.pypi.org)
  • Transparent Interception: Uses transparent DNS proxying; no application configuration required
  • Dynamic DNS: Resolved IPs are added to nftables with TTL for network-layer enforcement
  • Privilege Isolation: Requires CAP_NET_ADMIN only for the sidecar; application runs unprivileged
  • Graceful Degradation: Warns and disables enforcement if CAP_NET_ADMIN is missing instead of crashing

Architecture

The egress control is implemented as a Sidecar that shares the network namespace with the sandbox application.

Layer 1: DNS Proxy

  • Runs on 127.0.0.1:15353
  • iptables rules redirect all port 53 (DNS) traffic to this proxy
  • Filters queries based on the allowlist
  • Returns NXDOMAIN for denied domains

Layer 2: Network Filter (dns+nft mode)

When OPENSANDBOX_EGRESS_MODE=dns+nft:
  • Uses nftables to enforce IP-level allow/deny rules
  • Resolved IPs for allowed domains are added to dynamic allow sets with TTL (dynamic DNS)
  • At startup, the sidecar whitelists:
    • 127.0.0.1 (redirect target for the DNS proxy)
    • Nameserver IPs from /etc/resolv.conf (so DNS resolution and proxy upstream work, including private DNS)
Nameserver count is capped and invalid IPs are filtered. See Configuration for details.

Requirements

  • Runtime: Docker or Kubernetes
  • Capabilities: CAP_NET_ADMIN (for the sidecar container only)
  • Kernel: Linux kernel with iptables and nftables support

Configuration

Policy Bootstrap & Runtime

  • Default: Deny-all
  • Seed initial policy: Via OPENSANDBOX_EGRESS_RULES (JSON, same shape as /policy)
  • Runtime updates: Via /policy HTTP endpoint
  • Reset to deny-all: POST empty body to /policy

HTTP Service

Authentication: Use header OPENSANDBOX-EGRESS-AUTH: <token>

Egress Mode

Environment: OPENSANDBOX_EGRESS_MODE

DNS and Nameserver Whitelist (dns+nft mode)

In dns+nft mode, the sidecar automatically allows:
  • 127.0.0.1 — so packets redirected by iptables to the proxy are accepted by nft
  • Nameserver IPs from /etc/resolv.conf — so client DNS and proxy upstream work (e.g., private DNS)
Nameserver IPs are validated (unspecified and loopback are skipped) and capped:
See SECURITY-RISKS.md for trust and scope of this whitelist.

DoH/DoT Blocking

  • DoT (tcp/udp 853): Blocked by default
  • DoH over 443: Optional via OPENSANDBOX_EGRESS_BLOCK_DOH_443=true
    • If enabled without blocklist, all 443 traffic is dropped
  • DoH blocklist: OPENSANDBOX_EGRESS_DOH_BLOCKLIST="9.9.9.9,1.1.1.1/32,2001:db8::/32"

Runtime HTTP API

Default listen address: :18080 (override with OPENSANDBOX_EGRESS_HTTP_ADDR)

Endpoints

Policy Examples

DNS Allowlist (default deny)

DNS Blocklist (default allow)

IP/CIDR Only

Mixed DNS + IP/CIDR

Build & Run

Build Docker Image

Run Locally (Docker)

To test the sidecar with a sandbox application:
1

Start the Sidecar

Creates the network namespace:
CAP_NET_ADMIN is required for iptables redirection.
2

Configure Policy

After start, push policy via HTTP:
3

Start Application

Shares sidecar’s network:
4

Verify

Inside the application container:

Server Integration

The egress sidecar is automatically injected when using networkPolicy in sandbox creation requests.

Server Configuration

  • Only supported in Docker bridge mode
  • Requests with networkPolicy are rejected when network_mode=host or egress.image is not configured

Example Request

Sidecar Behavior

  • Main container shares the sidecar netns and explicitly drops NET_ADMIN
  • Sidecar keeps NET_ADMIN to manage iptables
  • IPv6 is disabled in the shared namespace when egress sidecar is injected
  • Sidecar image is pulled before start
  • Delete/expire/failure paths attempt to clean up the sidecar

Development

Project Structure

  • Language: Go 1.24+
  • Key Packages:
    • pkg/dnsproxy: DNS server and policy matching logic
    • pkg/iptables: iptables rule management
    • pkg/nftables: nftables static/dynamic rules and DNS-resolved IP sets
    • pkg/policy: Policy parsing and definition
  • Main (egress):
    • nameserver.go: Builds the list of IPs to whitelist for DNS in nft mode

Testing

E2E Benchmark: dns vs dns+nft

Compares dns (pass-through, no nft write) and dns+nft (sync AddResolvedIPs before each DNS reply):
More details in docs/benchmark.md.

Troubleshooting

Issue: Sidecar cannot set up iptables rulesSolution: Ensure the sidecar container has --cap-add=NET_ADMIN
Possible Causes:
  1. Check if the upstream DNS (from /etc/resolv.conf) is reachable
  2. In dns+nft mode, the sidecar whitelists nameserver IPs from resolv.conf at startup
  3. Check logs for [dns] whitelisting proxy listen + N nameserver(s)
  4. Ensure /etc/resolv.conf is readable and contains valid, reachable nameservers
Behavior:
  • The proxy prefers the first non-loopback nameserver from resolv.conf
  • If only loopback exists (e.g., Docker 127.0.0.11), it is used (proxy upstream traffic bypasses the redirect)
  • Fallback to 8.8.8.8 only when resolv.conf is empty or unreadable
Issue: Network policies are not being enforcedPossible Causes:
  1. If nftables apply fails, the sidecar falls back to dns mode
  2. Check logs for nftables errors
  3. Verify nft list table inet opensandbox
  4. Ensure CAP_NET_ADMIN is granted to the sidecar

Security Considerations

See SECURITY-RISKS.md for detailed security considerations including:
  • Nameserver whitelist trust model
  • DNS resolver scope and limitations
  • Best practices for production deployments

Support