Have you ever wondered what really happens when you create a Virtual Private Cloud (VPC) on AWS or GCP?
Behind the glossy dashboards and checkboxes, it’s all Linux, namespaces, bridges, and routing tables quietly working together.
In this guide, you’ll build your own local version of a cloud VPC.
You’ll use Linux network namespaces to create isolated environments, bridges to connect them, and iptables to manage NAT and firewall behavior.
And to tie it all together, you’ll run a small Python controller that automates the whole thing for you.
By the time you’re done, you’ll understand how cloud networking actually works, not just what buttons to click.
Project Overview
We’ll be using a simple setup called Bimbo VPC Controller.
It’s a command-line utility that lets you create virtual networks, connect them, enforce rules, and then clean them up again — all on your local machine.
Here’s the structure of the project folder:
/vpcctl-stage-4
│
├── demo.sh # Runs the full demo automatically
├── policy.json # Contains firewall and access policies
├── vpcctl.py # Main Python controller script
└── README.md # Documentation
Architecture Overview
Let’s break down how the system fits together.
Each VPC is represented as a network namespace.
Within each VPC, there are two subnets — one public and one private — each connected to its own Linux bridge.
The bridges are connected to your host interface (like ens5) through veth pairs.
NAT and firewall rules are applied using iptables.
Here’s a simple sketch of what that looks like:
+-------------------+
| VPC Namespace |
| (vpc1 / vpc2) |
+---------+---------+
|
veth pair
|
+---------+---------+
| Linux Bridge |
| (br-vpc1-pub) |
+---------+---------+
|
Public / Private Subnets
|
+---------+---------+
| NAT / Firewall |
| (iptables rules) |
+---------+---------+
|
Internet
So when you create VPC1, you’re really creating a namespace with its own virtual network and routing.
It behaves just like an AWS VPC, only it’s running on your laptop.
Setting Up
First, clone the project from GitHub and move into the directory:
git clone https://github.com/<your-username>/vpcctl-stage-4.git
cd vpcctl-stage-4
Make the scripts executable so they can run directly:
chmod +x demo.sh vpcctl.py
If you’d like to make the Python script available globally, create a symbolic link:
sudo ln -s "$(pwd)/vpcctl.py" /usr/local/bin/vpcctl
Now, install the required dependencies:
sudo apt update
sudo apt install -y iproute2 iptables curl netcat python3
You’re ready to go.
Running the Demo
The easiest way to see everything in action is by running the demo script.
It handles creation, configuration, and cleanup automatically.
sudo ./demo.sh
This will:
- Create two VPCs (vpc1 and vpc2),
- Add public and private subnets to each,
- Launch small web servers inside them,
- Enable NAT on the public subnets,
- Apply firewall policies,
- Test connectivity and isolation,
- Then tear everything down.
You can watch every step unfold in your terminal as it happens.
Command Line Usage
If you’d rather control things manually, you can use the vpcctl commands yourself.
Create a VPC
sudo vpcctl create vpc1 --cidr 10.0.0.0/16
This creates a Linux namespace named vpc1 and assigns it a network range.
Add Subnets
sudo vpcctl add-subnet vpc1 public --cidr 10.0.1.0/24
sudo vpcctl add-subnet vpc1 private --cidr 10.0.2.0/24
Each subnet gets its own bridge, connected through a veth pair.
This is how communication inside the VPC happens.
Launch a Web Server
sudo vpcctl launch-http vpc1 public --port 80
Starts a lightweight Python HTTP server inside the namespace.
You can test it with curl from another namespace later.
Apply a Firewall Policy
sudo vpcctl apply-policy policy.json
The controller reads your policy file and uses iptables to allow or block specific traffic.
Peer Two VPCs
sudo vpcctl peer vpc1 vpc2
This connects vpc1 and vpc2 through a virtual link so they can route traffic to each other.
Testing and Validation
After you’ve run the demo or created things manually, it’s time to verify everything is working as expected.
1. Connectivity Test Within a VPC
From the public subnet:
sudo ip netns exec vpc1-pub ping -c 2 10.0.2.1
This should succeed, confirming that the subnets in the same VPC can communicate.
2. NAT Test
From the public subnet:
sudo ip netns exec vpc1-pub curl http://example.com
This should work because NAT is enabled for the public subnet.
From the private subnet:
sudo ip netns exec vpc1-priv curl http://example.com
This should fail — private subnets are isolated from the internet by design.
3. Isolation Test Between VPCs
Before peering:
sudo ip netns exec vpc1-pub ping -c 2 10.1.1.1
This should fail, since vpc1 and vpc2 have no route between them.
After peering:
sudo ip netns exec vpc1-pub ping -c 2 10.1.1.1
This should now succeed.
You’ve just simulated cross-VPC communication.
Firewall and Policy Test
Let’s edit the policy file:
{
"vpc1": {
"allow": ["80/tcp"],
"deny": ["22/tcp"]
}
}
Apply it using:
sudo vpcctl apply-policy policy.json
Now test:
sudo ip netns exec vpc2-pub nc -vz 10.0.1.1 80
sudo ip netns exec vpc2-pub nc -vz 10.0.1.1 22
The first should connect, the second should fail.
That’s your firewall doing its job.
Cleaning Up
When you’re done experimenting, you can safely delete everything and return your system to normal.
sudo vpcctl delete vpc1
sudo vpcctl delete vpc2
Or simply use the demo’s built-in cleanup command:
sudo ./demo.sh clean
This removes:
- All network namespaces
- All bridges and veth pairs
- All iptables rules
- All logs and state files
Clean, complete, and ready for another experiment.
Wrapping Up
You’ve just built a fully functional cloud-style network stack — using nothing but Linux.
You saw how namespaces create isolation, how bridges connect subnets, and how iptables acts as your NAT gateway and firewall.
This project gives you more than a working script — it gives you intuition.
You now understand what happens when AWS says “launch VPC,” “add subnet,” or “enable NAT.”
And the best part?
You built it all locally, from the ground up.
:)
Top comments (0)