DEV Community

Cover image for Building and Testing a Mini VPC with Python and Linux Namespaces
Ifeanyi Nworji
Ifeanyi Nworji

Posted on • Edited on

Building and Testing a Mini VPC with Python and Linux Namespaces

Overview
In this project, I built a Mini Virtual Private Cloud (VPC) system on Linux using nothing but Python and native networking tools.
It mimics real AWS networking — with public/private subnets, NAT, VPC peering, and firewall policies — but all runs locally.

This setup is perfect for DevOps learners and cloud enthusiasts who want to see how networks actually work behind the scenes.


fig.1 VPC network diagram

  • Bridge (br0) → acts like your VPC switch

  • Namespaces → represent isolated networks

  • veth pairs → connect subnets to bridge

  • iptables NAT → allows outbound access only from the public subnet

Step 1: Setup

make setup
Enter fullscreen mode Exit fullscreen mode

Step 2: Create the VPC

sudo python3 vpcctl.py create-vpc vpc1 10.10.0.0/16 --public-interface wlp2s0
Enter fullscreen mode Exit fullscreen mode

This creates a virtual private cloud (VPC) simulation with the name vpc1 and a designated IP address range, linked to your actual public network interface.
10.10.0.0/16: This is the IP address range (specifically, a CIDR block) that the VPC will use for its internal network. The /16 denotes the specific size of the network, allowing for over 65,000 internal IP addresses within the VPC.

--public-interface wlp2s0: This flag tells the script to connect the simulated VPC to your actual physical network interface named wlp2s0(your system can have a different interface, run this command to see yours: ip addr show or ifconfig). This allows the resources inside your simulated VPC to communicate with the outside world (e.g., the internet) via your computer's real connection.

Step 3: Add Subnets

sudo python3 vpcctl.py add-subnet vpc1 public --type public --base-cidr 10.10.0.0/16

sudo python3 vpcctl.py add-subnet vpc1 private --type private --base-cidr 10.10.0.0/16
Enter fullscreen mode Exit fullscreen mode

Creates:

  • vpc1-public → 10.10.1.0/24 (Internet access)

  • vpc1-private → 10.10.2.0/24 (Internal only)

Step 4: Deploy Demo Applications
Run a web app in the public subnet

sudo ip netns exec vpc1-public python3 -m http.server 80
Enter fullscreen mode Exit fullscreen mode

From your host:

curl 10.10.1.2:80
Enter fullscreen mode Exit fullscreen mode

You should see the directory listing

Run a web app in the private subnet

sudo ip netns exec vpc1-private python3 -m http.server 80
Enter fullscreen mode Exit fullscreen mode

From host:

curl 10.10.2.2:80
Enter fullscreen mode Exit fullscreen mode

You’ll get no response — because private subnets aren’t exposed externally.

Step 5: Validate Connectivity
Communication within the same VPC

sudo ip netns exec vpc1-private ping -c 3 10.10.1.2
Enter fullscreen mode Exit fullscreen mode

Works (internal VPC communication).

Internet access from public subnet

sudo ip netns exec vpc1-public ping -c 3 8.8.8.8
Enter fullscreen mode Exit fullscreen mode

Works via NAT.

Internet access from private subnet

sudo ip netns exec vpc1-private ping -c 2 8.8.8.8
Enter fullscreen mode Exit fullscreen mode

Blocked — no default route to internet.

Step 6: Test Multiple VPCs and Peering
Create two VPCs

sudo python3 vpcctl.py create-vpc vpc2 10.20.0.0/16 --public-interface wlp2s0

sudo python3 vpcctl.py create-vpc vpc3 10.30.0.0/16 --public-interface wlp2s0
Enter fullscreen mode Exit fullscreen mode

Add subnets to VPC2 and VPC3

# PUBLIC SUBNET on vpc2
sudo python3 vpcctl.py add-subnet vpc2 public --type public --base-cidr 10.20.0.0/16

# PRIVATE SUBNET on vpc2
sudo python3 vpcctl.py add-subnet vpc2 private --type private --base-cidr 10.20.0.0/16

# PUBLIC SUBNET on vpc3
sudo python3 vpcctl.py add-subnet vpc3 public --type public --base-cidr 10.30.0.0/16

# PRIVATE SUBNET on vpc3
sudo python3 vpcctl.py add-subnet vpc3 private --type private --base-cidr 10.30.0.0/16
Enter fullscreen mode Exit fullscreen mode

Check isolation

sudo ip netns exec vpc1-public ping -c 2 10.20.1.2
Enter fullscreen mode Exit fullscreen mode

Blocked — fully isolated by default.

Peer them

sudo python3 vpcctl.py peer-vpc vpc1 vpc2
Enter fullscreen mode Exit fullscreen mode

Now ping again:

sudo ip netns exec vpc1-public ping -c 2 10.20.1.2
Enter fullscreen mode Exit fullscreen mode

Works (controlled communication after peering).

Step 7: Apply Security Policies (Firewall)

sudo python3 vpcctl.py apply-policies vpc2 --policies policies.json
Enter fullscreen mode Exit fullscreen mode

Policies.json:

[
  {
    "subnet": "10.20.2.0/24",
    "ingress": [
      {"port": 80, "protocol": "tcp", "action": "allow"},
      {"port": 22, "protocol": "tcp", "action": "deny"},
      {"port": 443, "protocol": "tcp", "action": "allow"}
    ]
  }
]
Enter fullscreen mode Exit fullscreen mode

would automatically block SSH access while keeping web traffic open.

Test policies:

Start a simple HTTP server on port 80 in the target namespace (vpc2)

sudo ip netns exec vpc2-public python3 -m http.server 80
Enter fullscreen mode Exit fullscreen mode

Test from the source namespace using nc:

sudo ip netns exec vpc2-private nc -vz 10.20.1.2 80
Enter fullscreen mode Exit fullscreen mode

Step 8: Cleanup

make cleanup
Enter fullscreen mode Exit fullscreen mode

Or

./cleanup.sh
Enter fullscreen mode Exit fullscreen mode

Removes:

  • All namespaces

  • The bridge

  • NAT/firewall rules

Ensures no residual configuration remains.

To run this with just one command:

make all
Enter fullscreen mode Exit fullscreen mode

and clean up with

make cleanup
Enter fullscreen mode Exit fullscreen mode

Github link

Top comments (0)