Skip to content
Guides · Sandboxes and isolation

What Can Reach a Sandbox, and What Can It Reach?

Updated October 27, 2026 .md

Short answer: Inbound, only ports you host on the HTTPS proxy, the SSH endpoint and the public IPv6 address reach a sandbox, and ufw closes IPv6 except SSH. Outbound, it reaches the internet. Other sandboxes, private ranges and port 25 are blocked. Sandboxer has no egress allowlist; restrict outbound yourself with ufw inside the VM.

At a glance#

We checked every row below on two small sandboxes on 2026-10-27.

Traffic What happens What we saw
Sandbox to the internet Allowed, IPv4 through NAT, IPv6 direct curl to pypi.org returned 200 on both
Sandbox to port 25 (SMTP) Blocked nc to smtp.gmail.com:25 timed out; port 587 connected
Sandbox to another of your sandboxes Blocked Timed out on its private IPv4 and its public IPv6, even after ufw allow
Sandbox to private ranges and link-local Blocked 10.x, 172.16.x, 192.168.x, 100.100.100.100 and 169.254.169.254 all failed
Sandbox to DNS The node's DNS relay answers /etc/resolv.conf points at 10.202.0.1
Internet to a hosted port Through the HTTPS proxy only sbx host URL returned 200; an unhosted port returned 404 Port not hosted
Internet to the SSH endpoint A public IPv4 host:port forwarded to port 22 Connected; key auth required
Internet to the IPv6 address Reaches the VM; ufw allows only port 22 Port 22 open, other ports timed out until sudo ufw allow
Internet to any other IPv4 port Nothing to connect to Timed out

There is no egress allowlist, domain filter or outbound firewall setting in Sandboxer. Outbound traffic is open by default. If you need to limit what an agent can call, do it inside the VM, as shown below.

Inbound: three ways in#

Hosted ports, through the proxy#

sbx host puts a port behind https://<subdomain>-<port>.box.sandboxer.com. It is private with a token by default, or public with --public. The proxy only forwards ports you hosted.

id=sb_zh0w0e4133    # your sandbox id from `sbx new`

sbx exec $id --detach "mkdir -p ~/site && cd ~/site && echo hello-from-8000 > index.html && python3 -m http.server 8000"
sbx exec $id --detach "mkdir -p ~/s2 && cd ~/s2 && echo not-hosted-9000 > index.html && python3 -m http.server 9000"
sbx host $id 8000 --public

curl -s -w ' %{http_code}\n' https://candid-rocky-basil-8000.box.sandboxer.com/
# hello-from-8000
#  200
curl -s -o /dev/null -w '%{http_code}\n' https://candid-rocky-basil-9000.box.sandboxer.com/
# 404    (the page says "Port 9000 is not hosted for this sandbox")

Both servers were listening. Only the hosted one was reachable. Hosted ports don't need a ufw rule: the VM's firewall already lets in IPv4, because on IPv4 only its own node can reach it.

sbx exec $id "sudo ufw status verbose"
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), allow (routed)
New profiles: skip

To                         Action      From
--                         ------      ----
22/tcp                     ALLOW IN    Anywhere                   # ssh
Anywhere                   ALLOW IN    Anywhere                   # sandboxer: IPv4 reaches this VM only via its node
22/tcp (v6)                ALLOW IN    Anywhere (v6)              # ssh

The SSH endpoint#

sbx info shows sshEndpoint, a public IPv4 host:port that is forwarded to the sandbox's port 22 while it runs. Ours was 62.238.91.250:22017. From outside, the port answered and asked for a key:

ssh -o BatchMode=yes -p 22017 user@62.238.91.250 true
# user@62.238.91.250: Permission denied (publickey).

Other ports on that IPv4 address timed out. sbx ssh uses a tunnel over HTTPS instead, so it works even where outbound SSH is blocked. See SSH.

The public IPv6 address#

Every sandbox has its own public IPv6 address:

sbx exec $id "ip -6 addr show scope global"
3: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 state UP qlen 1000
    inet6 2a01:4f9:3120:1d84::5b00:12/128 scope global nodad
       valid_lft forever preferred_lft forever

The machine we wrote this on has no IPv6, so we ran the outside checks from a server elsewhere on the internet that does. Port 22 was open. A server on port 8001 timed out until we opened it in ufw, then answered, then timed out again after we removed the rule:

# inside the sandbox: listen on IPv6 too (http.server binds IPv4 only by default)
sbx exec $id --detach "mkdir -p ~/s6 && cd ~/s6 && echo hello-over-ipv6 > index.html && python3 -m http.server 8001 --bind ::"
sbx exec $id "sudo ufw allow 8001/tcp"

# from a computer with IPv6
curl -s -m 6 http://[2a01:4f9:3120:1d84::5b00:12]:8001/
# hello-over-ipv6

sbx exec $id "sudo ufw delete allow 8001/tcp"
curl -s -m 6 http://[2a01:4f9:3120:1d84::5b00:12]:8001/; echo $?
# 28   (timed out)

Outbound: open by default#

sbx exec $id "curl -s -4 https://api.ipify.org; echo; curl -s -6 https://api6.ipify.org; echo; curl -sI https://pypi.org | head -1"
62.238.91.250
2a01:4f9:3120:1d84::5b00:12
HTTP/2 200

IPv4 leaves through the node's address. IPv6 leaves from the sandbox's own address. Bandwidth is shaped per VM, so one sandbox can't starve its neighbours.

What outbound is blocked#

sbx exec $id "nc -zv -w5 smtp.gmail.com 25; nc -zv -w5 smtp.gmail.com 587"
nc: connect to smtp.gmail.com (64.233.162.109) port 25 (tcp) timed out: Operation now in progress
Connection to smtp.gmail.com (2a00:1450:4010:c0a::6c) 587 port [tcp/submission] succeeded!

Send mail through your provider's submission port instead. Port 587 connected in our test.

The host, internal networks and link-local addresses are blocked too. This loop tries a TCP connection to each one:

sbx exec $id 'for t in 10.202.0.73:22 10.202.0.1:22 192.168.1.1:80 172.16.0.1:80 100.100.100.100:53 169.254.169.254:80; do
  timeout 4 bash -c "</dev/tcp/${t%:*}/${t#*:}" 2>/dev/null && echo "$t open" || echo "$t blocked"; done'
10.202.0.73:22 blocked
10.202.0.1:22 blocked
192.168.1.1:80 blocked
172.16.0.1:80 blocked
100.100.100.100:53 blocked
169.254.169.254:80 blocked

10.202.0.73 is the sandbox's own gateway, so even the host it runs on is out of reach.

Other sandboxes are blocked, even your own#

We started a second sandbox and tried to reach the first one from it, on its private IPv4 and its public IPv6:

other=sb_iajhvzwtws
sbx exec $other "nc -zv -w4 10.202.0.74 8000"
# nc: connect to 10.202.0.74 port 8000 (tcp) timed out
sbx exec $other "nc -zv -w4 2a01:4f9:3120:1d84::5b00:12 22"
# nc: connect to 2a01:4f9:3120:1d84::5b00:12 port 22 (tcp) timed out
sbx exec $id "sudo ufw allow 8001/tcp"
sbx exec $other "curl -s -m 6 http://[2a01:4f9:3120:1d84::5b00:12]:8001/; echo \$?"
# 28
sbx exec $other "curl -s https://candid-rocky-basil-8000.box.sandboxer.com/"
# hello-from-8000

Both of our sandboxes ran on the same server. Opening the port in ufw didn't help, because the node drops the traffic before it reaches the VM. The hosted URL worked. To connect two sandboxes, host a port and put your own authentication on it, or use the private URL's token.

DNS goes through the node's relay#

sbx exec $id "grep nameserver /etc/resolv.conf; dig +short @1.1.1.1 example.com +time=3 +tries=1; dig +short +tcp @1.1.1.1 example.com"
nameserver 10.202.0.1
;; communications error to 1.1.1.1#53: timed out
104.20.23.154
172.66.147.243

The resolver at 10.202.0.1 is the node's DNS relay, the one internal address a sandbox may reach. In our test, plain UDP queries to a public resolver over IPv4 timed out, while TCP and IPv6 queries to it answered. Keep the default resolver unless you have a reason not to.

Restrict outbound yourself with ufw#

ufw is already installed and active, so an allowlist is three steps: allow the hosts you need, allow the DNS relay, then deny everything else. ufw matches IP addresses, not names, so resolve the host first. This example allows only pypi.org:

sbx exec $id 'for ip in $(getent ahosts pypi.org | awk "{print \$1}" | sort -u); do
  sudo ufw allow out to $ip port 443 proto tcp comment pypi; done
sudo ufw allow out to 10.202.0.1 port 53 comment dns-relay
sudo ufw default deny outgoing'
Rule added
…
Default outgoing policy changed to 'deny'

Then check it:

sbx exec $id 'curl -s -m 8 -o /dev/null -w "pypi %{http_code}\n" https://pypi.org/simple/requests/
curl -s -m 8 -o /dev/null https://example.com; echo "example.com exit $?"
curl -s -m 8 -o /dev/null https://api.github.com; echo "api.github.com exit $?"'
pypi 200
example.com exit 28
api.github.com exit 28

Exit code 28 is curl's timeout.

pypi.org still worked, the other hosts timed out, and the public URL on port 8000 kept answering 200, because replies to inbound connections are still allowed. sbx exec kept working too: it doesn't use the sandbox's network. Undo it with sudo ufw default allow outgoing.

Three limits to know:

  • Docker containers skip these rules. With outbound denied in ufw, docker run --rm alpine wget https://example.com still succeeded, even after sudo ufw default deny routed. Docker puts its own rules first. Use its DOCKER-USER chain instead, as below.
  • The addresses change. A CDN can move a host to new IPs. Re-run the allow loop when a host stops working.
  • Root can undo it. The default user has passwordless sudo, so code that runs as user can turn the firewall off again. Run untrusted code as a separate user without sudo if that matters to you.

Limit Docker containers too#

sbx exec $id 'sudo iptables -I DOCKER-USER -i docker0 -j REJECT
for ip in $(getent ahostsv4 pypi.org | awk "{print \$1}" | sort -u); do
  sudo iptables -I DOCKER-USER -i docker0 -d $ip -p tcp --dport 443 -j RETURN; done
sudo iptables -I DOCKER-USER -i docker0 -d 10.202.0.1 -p udp --dport 53 -j RETURN
docker run --rm alpine wget -q -T 8 -O /dev/null https://example.com; echo "example.com exit $?"
docker run --rm alpine wget -q -T 8 -O /dev/null https://pypi.org/simple/; echo "pypi exit $?"'
wget: can't connect to remote host (172.66.147.243): Connection refused
example.com exit 1
pypi exit 0

Rules inserted with -I go to the top, which is why the REJECT comes first in the script: it ends up last. sudo iptables -F DOCKER-USER removes them.

FAQ#

Does Sandboxer have an egress allowlist or domain firewall?#

No. Outbound traffic is open by default, except SMTP port 25, other sandboxes, the host and internal networks. To allow only certain hosts, set ufw's outgoing policy to deny inside the VM and allow the addresses you need.

Do I need a ufw rule for a hosted port?#

No. sbx host works without one, because the VM's firewall already accepts IPv4 from its node, and the proxy only forwards ports you hosted. You need sudo ufw allow <port> only to serve a port directly on the IPv6 address.

Can two of my sandboxes talk to each other?#

Not directly. In our test, traffic between two sandboxes was blocked on both private IPv4 and public IPv6, even with the port open in ufw. Connect them through a hosted URL and add your own authentication.

Can code in a sandbox reach the host or a cloud metadata service?#

No. Connections to the gateway, RFC 1918 ranges, 100.100.100.100 and 169.254.169.254 all failed in our test. The only internal address a sandbox can reach is the node's DNS relay. The agent inside the VM talks to the host over vsock, not the network.

Why can't I query 1.1.1.1 over UDP?#

In our test, UDP DNS queries to a public resolver over IPv4 timed out, while TCP and IPv6 queries answered. Use the default resolver in /etc/resolv.conf, or query over TCP.

More guides

Top AI sandbox platforms for code execution in 2026, ranked

For running AI-written code we rank Sandboxer, Freestyle and E2B first: each gives code its own VM with an API or SDK and can pause with memory. Pick Daytona for Windows or GPUs, Modal or Northflank for GPUs at scale, E2B or Northflank to run in your own cloud, and Vercel Sandbox if your app lives on Vercel.

Read the guide
Best sandboxes for running coding agents (Claude Code, Codex, Gemini CLI) in 2026, ranked

For coding agents we rank Sandboxer first: a full Ubuntu VM with Claude Code and Codex preinstalled, Docker, and stop-and-resume that keeps the agent's session in memory. Freestyle and Amp Orbs also keep memory across pauses. Pick E2B for prebuilt agent templates on open source, Docker Sandboxes for free local runs, and Codespaces if you live in GitHub.

Read the guide
Best Daytona sandbox alternatives in 2026, ranked

The best Daytona alternatives depend on why you're switching. For a full Linux microVM on every sandbox with memory-saving stop and Docker, we rank Sandboxer first. E2B suits open source and self-hosting, Modal massive short-job fleets, Northflank bring-your-own-cloud with GPUs, and Vercel Sandbox apps on Vercel.

Read the guide
Best E2B alternatives in 2026, ranked

If you're leaving E2B for longer sessions or a fuller machine, we rank Sandboxer first, then Freestyle: both give each sandbox a full Linux VM that keeps memory across pauses, with Docker and no short session cap. Pick Daytona for Windows or GPUs, Northflank for bring-your-own-cloud, and stay on E2B if you need open source.

Read the guide