Dual-Network Router Lab Playground
Five Ubuntu VMs across public and private subnets, joined by a dual-homed router. The private subnet has no direct Internet access.

Overview
This playground contains five Ubuntu 24.04 VMs arranged into two separate Layer 2 networks. Four VMs are ordinary hosts, while box-05 is dual-homed and routes traffic between the two subnets.
The private subnet is deliberately air-gapped from the Internet. Its hosts can communicate with the public-side VMs through the router, but the router does not perform NAT or masquerading for them.
Topology
| Role | Machine | Interface | Address | Internet access |
|---|---|---|---|---|
| Private host 1 | box-01 | eth0 → private | 10.10.0.10/24 | No |
| Private host 2 | box-02 | eth0 → private | 10.10.0.11/24 | No |
| Public host 1 | box-03 | eth0 → public | 10.20.0.10/24 | Yes |
| Public host 2 | box-04 | eth0 → public | 10.20.0.11/24 | Yes |
| Router | box-05 | eth0 → private | 10.10.0.254/24 | Via its public interface |
| Router | box-05 | eth1 → public | 10.20.0.254/24 | Yes |
Private network
- Name:
private - Subnet:
10.10.0.0/24 - Members:
box-01,box-02, and the private interface ofbox-05 - Marked
private: true, so the platform supplies neither a default route nor Internet NAT - Hosts route the public subnet through
10.10.0.254
Public network
- Name:
public - Subnet:
10.20.0.0/24 - Members:
box-03,box-04, and the public interface ofbox-05 - Uses the platform-provided default route through
10.20.0.1 - Hosts route the private subnet through
10.20.0.254
Routing setup
An init task enables IPv4 forwarding on box-05:
printf 'net.ipv4.ip_forward=1\n' > /etc/sysctl.d/99-router.conf
sysctl --system
The leaf VMs receive these static routes:
# box-01 and box-02
ip route replace 10.20.0.0/24 via 10.10.0.254
# box-03 and box-04
ip route replace 10.10.0.0/24 via 10.20.0.254
No NAT rules are installed on box-05. Consequently, private hosts can reach the public subnet but cannot use the router as an Internet gateway.
Expected connectivity
| Source | Destination | Expected result |
|---|---|---|
| Private host | Another private host | Directly reachable |
| Public host | Another public host | Directly reachable |
| Private host | Public host | Routed through box-05 |
| Public host | Private host | Routed through box-05 |
| Public host | Internet | Reachable |
| Private host | Internet | Unreachable |
Quick checks
From box-01, confirm that cross-subnet routing works while Internet access remains unavailable:
ip route
ping -c 2 10.20.0.10
ping -c 2 1.1.1.1 # expected to fail
From box-03, test the reverse route and Internet connectivity:
ping -c 2 10.10.0.10
ping -c 2 1.1.1.1
On box-05, inspect both interfaces and verify forwarding:
ip -brief address
ip route
sysctl net.ipv4.ip_forward
The last command should print net.ipv4.ip_forward = 1.
A real VM, not a container
Get root on a VM with its own kernel, so Docker, Kubernetes, and systemd just work.
Read the docs →
SSH from browser or CLI
Use the built-in web terminal, or connect with labctl ssh, plain ssh, scp, or rsync.
Read the docs →
Drive it with AI
Let Claude, Codex, or any MCP client start this playground and run commands in it.
Read the docs →
Expose HTTP(S) ports
Give any web app running inside the VM a public URL - for yourself or to share with others.
Read the docs →
Share terminals
Invite others into your terminal session, or open it yourself from another device.
Read the docs →
Customize with init scripts
Add shell scripts that run at boot to install packages, clone repos, or seed test data.
Read the docs →
Private networking
VMs reach the internet via NAT with no public IP; several VMs share bridge networks.
Read the docs →
Ephemeral or persistent
By default, VMs are destroyed when the session ends; enable persistence to keep the disks for next time.
Read the docs →
Built-in container registry
A private registry.iximiuz.com for every playground to share images across services and VMs.
Read the docs →