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) # sshThe 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 foreverThe 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 200IPv4 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 blocked10.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-8000Both 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.243The 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 28Exit 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.comstill succeeded, even aftersudo ufw default deny routed. Docker puts its own rules first. Use itsDOCKER-USERchain 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
userhas passwordless sudo, so code that runs asusercan 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 0Rules 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.
Related#
More guides
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.
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.
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.
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.